Java тілінде көп ағынды шешетін мәселелер
Негізінде, Java көп ағынды екі негізгі мәселені шешу үшін ойлап табылды:-
Бір уақытта бірнеше әрекетті орындаңыз.
Жоғарыдағы мысалда әртүрлі жіптер (яғни отбасы мүшелері) параллельді түрде бірнеше әрекеттерді орындады: ыдыстарды жуды, дүкенге барды, заттарды бүктеп тастады.
Көбірек «бағдарламашы» мысалын келтіруге болады. Сізде пайдаланушы интерфейсі бар бағдарлама бар деп елестетіңіз. Жалғастыру түймешігін басқан кезде бағдарламада кейбір есептеулер орын алуы керек және пайдаланушы келесі интерфейс экранын көруі керек. Егер бұл әрекеттер дәйекті түрде орындалса, «Жалғастыру» түймесін басқаннан кейін бағдарлама жай ғана қатып қалады. Пайдаланушы барлық ішкі есептеулер аяқталғанша және бағдарлама интерфейс сызыла бастайтын бөлікке жеткенше «Жалғастыру» түймесі бар бірдей экранды көреді.
Ал, бір-екі minutes күтейік!
Біз сондай-ақ бағдарламамызды қайта жасай аламыз немесе бағдарламашылар айтқандай, «параллельді» жасай аламыз. Қажетті есептеулер бір ағында, ал интерфейсті көрсету басқасында орындалсын. Көптеген компьютерлерде бұл үшін жеткілікті ресурстар бар. Бұл жағдайда бағдарлама «ақымақ» болмайды және пайдаланушы ішінде не болып жатқаны туралы алаңдамай интерфейс экрандары арасында тыныштықпен қозғалады. Бұл кедергі жасамайды :)
-
Есептерді жылдамdate.
Мұнда бәрі әлдеқайда қарапайым. Егер біздің процессорда бірнеше ядролар болса, ал процессорлардың көпшілігі қазір көп ядролы болса, біздің міндеттер тізімін бірнеше ядролармен қатар шешуге болады. Әлбетте, егер бізге 1000 мәселені шешу керек болса және олардың әрқайсысы бір секундта шешілсе, бір ядро 1000 секундта тізімді жеңеді, екі ядро 500 секундта, үшеуі 333 секундтан сәл астам уақыт ішінде және т.б.
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
Көп ағынды тудыратын мәселелер
Кітаптармен мысалда сіз көп ағынды қолдану өте маңызды мәселелерді шешетінін және оны пайдалану біздің бағдарламалардың жұмысын тездететінін көрдіңіз. Көптеген жағдайларда - көп рет. Бірақ көп ағынды күрделі тақырып деп бекер айтылмаған. Өйткені, егер дұрыс пайдаланылмаса, оны шешудің орнына проблемалар тудырады. Мен «мәселелерді жасау» дегенде, мен дерексіз нәрсені білдірмеймін. Көп ағынды тудыруы мүмкін екі нақты мәселе бар: тұйықтау және жарыс жағдайы. Тұйықталу - бұл бірнеше ағындар бір-біріне ие болған ресурстарды күтетін және олардың ешқайсысы орындауды жалғастыра алмайтын жағдай. Бұл туралы алдағы дәрістерде толығырақ айтатын боламыз, бірақ әзірге мына мысал жеткілікті: ағын-1 қандай да бір Объект-1-мен, ал ағын-2 an object-2-мен жұмыс істеп жатыр деп елестетіңіз. Бағдарлама келесідей жазылған:- Thread-1 2-an objectпен жұмысын тоқтатып, Объект-1-ге ауысқаннан кейін 1-ші тармақ Объекті-1-мен жұмысын тоқтатады және 2-an object-2-ге ауысады.
- Thread-1 1-an objectпен жұмысын тоқтатып, Объект-2-ге ауысқаннан кейін 2-ші тармақ Объекті-2-мен жұмысын тоқтатады және Объект-1-ге ауысады.
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 ағыны орындалды Сценарий қызық па? :) Және бәрі біздің бағдарламаның жұмысы ағындардың орындалу ретіне байланысты. Біраз реттілік бұзылса, біздің ас үйіміз тозаққа айналады, ал есінен танып қалған робот айналасындағының бәрін бұзады. Бұл сонымен қатар бірнеше рет еститін көп ағынды бағдарламалауда жиі кездесетін мәселе. Дәріс соңында мен сізге көп ағындылық туралы кітапты ұсынғым келеді.
GO TO FULL VERSION