JavaRush /Java блогы /Random-KK /Java тіліндегі көп ағынды: мәні, артықшылықтары және жалп...

Java тіліндегі көп ағынды: мәні, артықшылықтары және жалпы қателері

Топта жарияланған
Сәлеметсіз бе! Біріншіден, құттықтаймыз: сіз Java тіліндегі Multithreading тақырыбына жеттіңіз! Бұл елеулі жетістік, алда әлі алда. Бірақ дайын болыңыз: бұл курстағы ең қиын тақырыптардың бірі. Мәселе мұнда күрделі сыныптардың немесе көптеген әдістердің қолданылуында емес: керісінше, тіпті екі ондаған да жоқ. Ойлауды аздап өзгерту керек. Бұрын бағдарламаларыңыз ретімен орындалатын. Кодтың кейбір жолдары басқаларына, кейбір әдістер басқаларына сәйкес келді және жалпы алғанда бәрі түсінікті болды. Алдымен бір нәрсені есептеңіз, содан кейін нәтижені консольде көрсетіңіз, содан кейін бағдарламаны тоқтатыңыз. Көп ағынды түсіну үшін параллельділік тұрғысынан ойлаған дұрыс. Өте қарапайым нәрседен бастайық :) Java тіліндегі көп ағынды: мәні, артықшылықтары және жалпы қателері - 1Сіздің отбасыңыз бір үйден екінші үйге көшіп жатыр деп елестетіңіз. Көшудің маңызды бөлігі - кітаптарыңызды орау. Сіз көп кітап жинадыңыз, оларды жәшіктерге салуыңыз керек. Енді сен ғана боссың. Анам тамақ әзірлеп жатыр, ағасы киім жинап жатыр, ал әпкесі дүкенге кетті. Жалғыз сіз, кем дегенде, басқара аласыз және ерте ме, кеш пе, сіз тіпті тапсырманы өзіңіз аяқтайсыз, бірақ бұл көп уақытты алады. Алайда 20 minutesтан кейін әпкең дүкеннен қайтады, оның басқа шаруасы жоқ. Сондықтан ол сізге қосыла алады. Тапсырма өзгеріссіз қалды: кітаптарды қораптарға салу. Ол екі есе жылдам жүгіреді. Неліктен? Өйткені жұмыс параллель орындалады. Екі түрлі «жіп» (сіз және сіздің әпкеңіз) бір уақытта бір тапсырманы орындап жатырсыз және егер ештеңе өзгермесе, сіз бәрін жалғыз жасайтын жағдаймен салыстырғанда уақыт айырмашылығы өте үлкен болады. Егер сіздің ағаңыз тез арада тапсырмасын орындаса, ол сізге көмектесе алады және іс одан да жылдам болады.

Java тілінде көп ағынды шешетін мәселелер

Негізінде, Java көп ағынды екі негізгі мәселені шешу үшін ойлап табылды:
  1. Бір уақытта бірнеше әрекетті орындаңыз.

    Жоғарыдағы мысалда әртүрлі жіптер (яғни отбасы мүшелері) параллельді түрде бірнеше әрекеттерді орындады: ыдыстарды жуды, дүкенге барды, заттарды бүктеп тастады.

    Көбірек «бағдарламашы» мысалын келтіруге болады. Сізде пайдаланушы интерфейсі бар бағдарлама бар деп елестетіңіз. Жалғастыру түймешігін басқан кезде бағдарламада кейбір есептеулер орын алуы керек және пайдаланушы келесі интерфейс экранын көруі керек. Егер бұл әрекеттер дәйекті түрде орындалса, «Жалғастыру» түймесін басқаннан кейін бағдарлама жай ғана қатып қалады. Пайдаланушы барлық ішкі есептеулер аяқталғанша және бағдарлама интерфейс сызыла бастайтын бөлікке жеткенше «Жалғастыру» түймесі бар бірдей экранды көреді.

    Ал, бір-екі minutes күтейік!

    Java тіліндегі көп ағынды: мәні, артықшылықтары және жалпы қателері - 3

    Біз сондай-ақ бағдарламамызды қайта жасай аламыз немесе бағдарламашылар айтқандай, «параллельді» жасай аламыз. Қажетті есептеулер бір ағында, ал интерфейсті көрсету басқасында орындалсын. Көптеген компьютерлерде бұл үшін жеткілікті ресурстар бар. Бұл жағдайда бағдарлама «ақымақ» болмайды және пайдаланушы ішінде не болып жатқаны туралы алаңдамай интерфейс экрандары арасында тыныштықпен қозғалады. Бұл кедергі жасамайды :)

  2. Есептерді жылдамdate.

    Мұнда бәрі әлдеқайда қарапайым. Егер біздің процессорда бірнеше ядролар болса, ал процессорлардың көпшілігі қазір көп ядролы болса, біздің міндеттер тізімін бірнеше ядролармен қатар шешуге болады. Әлбетте, егер бізге 1000 мәселені шешу керек болса және олардың әрқайсысы бір секундта шешілсе, бір ядро ​​​​1000 секундта тізімді жеңеді, екі ядро ​​​​500 секундта, үшеуі 333 секундтан сәл астам уақыт ішінде және т.б.

Бірақ, сіз дәрісте оқығаныңыздай, қазіргі заманғы жүйелер өте ақылды, тіпті бір есептеуіш ядрода олар тапсырмалар кезектесіп орындалғанда параллелизмді немесе псевдопараллелизмді жүзеге асыра алады. Жалпы нәрселерден нақтыларға көшейік және Java кітапханасындағы көп ағынмен байланысты негізгі класс – java.lang.Thread-пен танысайық. Қатаң айтқанда, Java-дағы ағындар класс даналарымен ұсынылған Thread. Яғни, 10 ағынды құру және іске қосу үшін осы класстың 10 нысаны қажет болады. Ең қарапайым мысалды жазайық:
public class MyFirstThread extends Thread {

   @Override
   public void run() {
       System.out.println("I'm Thread! My name is " + getName());
   }
}
Ағындарды жасау және іске қосу үшін класс жасап, оны java.lang. Threadжәне ондағы әдісті қайта анықтау run(). Соңғысы өте маңызды. Дәл осы әдісте run()біз ағынның орындалуы керек логиканы белгілейміз. Енді, егер біз дананы жасап MyFirstThread, оны іске қоссақ, әдіс run()консольге оның аты бар жолды басып шығарады: әдіс getName()автоматты түрде тағайындалатын ағынның «жүйелік» атауын басып шығарады. Дегенмен, шын мәнінде, неге «егер»? Жасап, сынап көрейік!
public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {

           MyFirstThread thread = new MyFirstThread();
           thread.start();
       }
   }
}
Консоль шығысы: Мен Threadмін! Менің атым Thread-2 I'm Thread! Менің атым Thread-1 I'm Thread! Менің атым Thread-0 I'm Thread! Менің атым Thread-3 I'm Thread! Менің атым Thread-6 I'm Thread! Менің атым Thread-7 I'm Thread! Менің атым Thread-4 I'm Thread! Менің атым Thread-5 I'm Thread! Менің атым Thread-9 I'm Thread! Менің атым Thread-8MyFirstThread Біз мұраға алатын 10 ағынды (нысандарды) жасаймыз Threadжәне оларды нысан әдісін шақыру арқылы іске қосамыз start(). Әдісті шақырғаннан кейін start()оның әдісі жұмыс істей бастайды run()және оған жазылған логика орындалады. Назар аударыңыз: жіп атаулары ретсіз. Бұл өте қызық, неге олар кезекпен орындалмады: Thread-0, Thread-1, Thread-2және т.б. Бұл стандартты, «тізбекті» ойлаудың жұмыс істемейтінінің нақты мысалы. Өйткені, бұл жағдайда біз тек 10 ағынды құру және іске қосу пәрмендерін береміз. Оларды қандай ретпен іске қосу керектігін ағынды жоспарлаушы шешеді: операциялық жүйенің ішіндегі арнайы механизм. Ол қаншалықты нақты құрылымдалған және қандай принцип бойынша шешім қабылдайды - бұл өте күрделі тақырып, және біз оған қазір енбейміз. Ең бастысы, бағдарламашы ағынның орындалу ретін басқара алмайтындығын есте ұстаған жөн. Жағдайдың маңыздылығын түсіну үшін main()жоғарыдағы мысалдағы әдісті тағы бірнеше рет іске қосып көріңіз. Екінші консоль шығысы: Мен Threadмін! Менің атым Thread-0 I'm Thread! Менің атым Thread-4 I'm Thread! Менің атым Thread-3 I'm Thread! Менің атым Thread-2 I'm Thread! Менің атым Thread-1 I'm Thread! Менің атым Thread-5 I'm Thread! Менің атым Thread-6 I'm Thread! Менің атым Thread-8 I'm Thread! Менің атым Thread-9 I'm Thread! Менің атым Thread-7 Үшінші консоль шығысы: I'm Thread! Менің атым Thread-0 I'm Thread! Менің атым Thread-3 I'm Thread! Менің атым Thread-1 I'm Thread! Менің атым Thread-2 I'm Thread! Менің атым Thread-6 I'm Thread! Менің атым Thread-4 I'm Thread! Менің атым Thread-9 I'm Thread! Менің атым Thread-5 I'm Thread! Менің атым Thread-7 I'm Thread! Менің атым Thread-8

Көп ағынды тудыратын мәселелер

Кітаптармен мысалда сіз көп ағынды қолдану өте маңызды мәселелерді шешетінін және оны пайдалану біздің бағдарламалардың жұмысын тездететінін көрдіңіз. Көптеген жағдайларда - көп рет. Бірақ көп ағынды күрделі тақырып деп бекер айтылмаған. Өйткені, егер дұрыс пайдаланылмаса, оны шешудің орнына проблемалар тудырады. Мен «мәселелерді жасау» дегенде, мен дерексіз нәрсені білдірмеймін. Көп ағынды тудыруы мүмкін екі нақты мәселе бар: тұйықтау және жарыс жағдайы. Тұйықталу - бұл бірнеше ағындар бір-біріне ие болған ресурстарды күтетін және олардың ешқайсысы орындауды жалғастыра алмайтын жағдай. Бұл туралы алдағы дәрістерде толығырақ айтатын боламыз, бірақ әзірге мына мысал жеткілікті: Java тіліндегі көп ағынды: мәні, артықшылықтары және жалпы қателері - 4 ағын-1 қандай да бір Объект-1-мен, ал ағын-2 an object-2-мен жұмыс істеп жатыр деп елестетіңіз. Бағдарлама келесідей жазылған:
  1. Thread-1 2-an objectпен жұмысын тоқтатып, Объект-1-ге ауысқаннан кейін 1-ші тармақ Объекті-1-мен жұмысын тоқтатады және 2-an object-2-ге ауысады.
  2. Thread-1 1-an objectпен жұмысын тоқтатып, Объект-2-ге ауысқаннан кейін 2-ші тармақ Объекті-2-мен жұмысын тоқтатады және Объект-1-ге ауысады.
Көп ағынды терең білмесеңіз де, одан ештеңе шықпайтынын оңай түсінуге болады. Жіптер ешқашан орнын ауыстырмайды және бір-бірін мәңгі күтеді. Қате анық көрінеді, бірақ іс жүзінде олай емес. Сіз оны бағдарламаға оңай рұқсат ете аласыз. Біз келесі дәрістерде тығырықтан тудыратын code мысалдарын қарастырамыз. Айтпақшы, Quora тығырықтан шығудың не екенін түсіндіретін тамаша нақты мысалға ие . «Үндістанның кейбір штаттарында фермер ретінде тіркелмейінше, олар сізге ауылшаруашылық жерлерін сатпайды. Алайда ауыл шаруашылығы мақсатындағы жеріңіз болмаса, сіз фермер ретінде тіркелмейсіз». Керемет, мен не айта аламын! :) Енді жарыс шарты туралы - жарыс күйі. Жарыс шарты жүйенің немесе қолданбаның жұмысы code бөліктерінің орындалу ретіне байланысты болатын көп ағынды жүйедегі немесе қолданбадағы жобалық ақау болып табылады. Жұмыс ағындары бар мысалды есте сақтаңыз: Java тіліндегі көп ағынды: мәні, артықшылығы және жалпы қателері - 5
public class MyFirstThread extends Thread {

   @Override
   public void run() {
       System.out.println("Выполнен поток " + getName());
   }
}

public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {

           MyFirstThread thread = new MyFirstThread();
           thread.start();
       }
   }
}
Енді бағдарлама тағам дайындайтын роботтың жұмысына жауап береді деп елестетіңіз! Жіп-0 жұмыртқаны тоңазытқыштан шығарады. 1 ағыны пешті қосады. Stream-2 қуырғыш табаны алып, пешке қояды. 3-ағында пеште от жағылады. Ағын 4 табаға май құйыңыз. Ағын 5 жұмыртқаны сындырып, оларды қуырғыш табаға құйып жібереді. 6-шы ағын снарядтарды қоқыс жәшігіне тастайды. Stream-7 дайын жұмыртқаны ыстықтан алып тастайды. Поток-8 тарелкаға жұмыртқаны салады. Stream 9 ыдыстарды жуады. Біздің бағдарламаның нәтижелерін қараңыз: Thread-0 орындалды Тақырып-2 орындалды Жіп-1 ағын орындалды Тақырып-4 ағын орындалды Тақырып-9 ағын орындалды Тақырып-5 ағын орындалды Тақырып-8 ағын орындалды Тақырып-7 ағын орындалды Тақырып-7 орындалды. ағын орындалды -3 Thread-6 ағыны орындалды Сценарий қызық па? :) Және бәрі біздің бағдарламаның жұмысы ағындардың орындалу ретіне байланысты. Біраз реттілік бұзылса, біздің ас үйіміз тозаққа айналады, ал есінен танып қалған робот айналасындағының бәрін бұзады. Бұл сонымен қатар бірнеше рет еститін көп ағынды бағдарламалауда жиі кездесетін мәселе. Дәріс соңында мен сізге көп ағындылық туралы кітапты ұсынғым келеді.
Java тіліндегі көп ағынды: мәні, артықшылықтары және жалпы қателері - 6
«Java Concurrency in Practice» 2006 жылы жазылған, бірақ өзектілігін жоғалтқан жоқ. Ол Java тіліндегі көп ағынды бағдарламалауды қамтиды, оның негіздерінен бастап және ең жиі кездесетін қателер мен антипаттерндердің тізімімен аяқталады. Егер сіз көп ағынды бағдарламалау гурусы болуды шешсеңіз, бұл кітап міндетті түрде оқылады. Келесі дәрістерде кездескенше! :)
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION