Java'da multithreading hal qiladigan muammolar
Aslida, Java multithreading ikkita asosiy muammoni hal qilish uchun ixtiro qilingan:-
Bir vaqtning o'zida bir nechta amallarni bajaring.
Yuqoridagi misolda turli xil iplar (ya'ni, oila a'zolari) parallel ravishda bir nechta harakatlarni amalga oshirdilar: idishlarni yuvdilar, do'konga bordilar, narsalarni katladilar.
Ko'proq "dasturchi" misolini keltirish mumkin. Tasavvur qiling-a, sizda foydalanuvchi interfeysi bo'lgan dastur mavjud. Davom etish tugmasi bosilganda, dastur ichida ba'zi hisob-kitoblar amalga oshirilishi kerak va foydalanuvchi quyidagi interfeys ekranini ko'rishi kerak. Agar ushbu harakatlar ketma-ket bajarilsa, "Davom etish" tugmasini bosgandan so'ng, dastur shunchaki muzlaydi. Foydalanuvchi "Davom etish" tugmasi bilan bir xil ekranni barcha ichki hisob-kitoblar tugagunga qadar va dastur interfeys chizilishi boshlanadigan qismga yetguncha ko'radi.
Xo'sh, bir necha daqiqa kutamiz!
Biz dasturimizni qayta ishlab chiqishimiz yoki dasturchilar aytganidek, “parallellashtirish”imiz ham mumkin. Kerakli hisob-kitoblar bitta ipda, interfeysni ko'rsatish boshqasida amalga oshirilsin. Aksariyat kompyuterlarda buning uchun yetarli resurslar mavjud. Bunday holda, dastur "ahmoq" bo'lmaydi va foydalanuvchi ichkarida nima sodir bo'layotganidan xavotirlanmasdan, interfeys ekranlari o'rtasida xotirjamlik bilan harakat qiladi. Bu aralashmaydi :)
-
Hisob-kitoblarni tezlashtiring.
Bu erda hamma narsa ancha sodda. Agar bizning protsessorimiz bir nechta yadroga ega bo'lsa va ko'pchilik protsessorlar endi ko'p yadroli bo'lsa, bizning vazifalarimiz ro'yxati bir nechta yadrolar tomonidan parallel ravishda hal qilinishi mumkin. Shubhasiz, agar biz 1000 ta muammoni hal qilishimiz kerak bo'lsa va ularning har biri bir soniyada hal etilsa, bitta yadro 1000 soniyada, ikkita yadro 500 soniyada, uchtasi 333 soniyadan ko'proq vaqt ichida va hokazo.
Thread
. Ya'ni, 10 ta ip yaratish va ishga tushirish uchun sizga ushbu sinfning 10 ta ob'ekti kerak bo'ladi. Eng oddiy misolni yozamiz:
public class MyFirstThread extends Thread {
@Override
public void run() {
System.out.println("I'm Thread! My name is " + getName());
}
}
Tarmoqlarni yaratish va ishga tushirish uchun biz sinf yaratishimiz va uni java.lang
. Thread
va undagi usulni bekor qiling run()
. Oxirgisi juda muhim. Aynan usulda run()
biz ipimiz bajarishi kerak bo'lgan mantiqni belgilaymiz. Endi, agar biz misol yaratsak MyFirstThread
va uni ishga tushirsak, usul run()
konsolga o'z nomi bilan chiziqni chop etadi: usul getName()
avtomatik ravishda tayinlangan ipning "tizim" nomini chop etadi. Garchi, aslida, nima uchun "agar"? Keling, yaratamiz va sinab ko'ramiz!
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
MyFirstThread thread = new MyFirstThread();
thread.start();
}
}
}
Konsol chiqishi: Men Threadman! Mening ismim Thread-2 Men mavzu! Mening ismim Thread-1 Men mavzu! Mening ismim Thread-0 Men mavzu! Mening ismim Thread-3 Men mavzu! Mening ismim Thread-6 Men mavzu! Mening ismim Thread-7 Men mavzu! Mening ismim Thread-4 Men mavzu! Mening ismim Thread-5 Men mavzu! Mening ismim Thread-9 Men mavzu! Mening ismim Thread-8MyFirstThread
Biz meros qilib oladigan 10 ta mavzuni (ob'ektni) yaratamiz Thread
va ularni ob'ekt usulini chaqirish orqali ishga tushiramiz start()
. Metodni chaqirgandan so'ng , start()
uning usuli ishlay boshlaydi run()
va unda yozilgan mantiq bajariladi. Iltimos, diqqat qiling: mavzu nomlari tartibda emas. Bu juda g'alati, nega ular o'z navbatida qatl qilinmadi: Thread-0
, Thread-1
, Thread-2
va hokazo? Bu standart, "ketma-ket" fikrlash ishlamasligiga aniq misol. Gap shundaki, bu holda biz faqat 10 ta ip yaratish va ishga tushirish uchun buyruq beramiz. Ularni qanday tartibda ishga tushirish kerakligi mavzuni rejalashtiruvchi tomonidan hal qilinadi: operatsion tizim ichidagi maxsus mexanizm. U qanday qilib aniq tuzilgan va qanday printsip asosida qaror qabul qiladi - bu juda murakkab mavzu va biz hozir unga sho'ng'imaymiz. Esda tutish kerak bo'lgan asosiy narsa shundaki, dasturchi ipni bajarish ketma-ketligini nazorat qila olmaydi. Vaziyatning jiddiyligini tushunish uchun main()
yuqoridagi misoldagi usulni yana bir necha marta ishlatishga harakat qiling. Ikkinchi konsol chiqishi: Men Threadman! Mening ismim Thread-0 Men mavzu! Mening ismim Thread-4 Men mavzu! Mening ismim Thread-3 Men mavzu! Mening ismim Thread-2 Men mavzu! Mening ismim Thread-1 Men mavzu! Mening ismim Thread-5 Men mavzu! Mening ismim Thread-6 Men mavzu! Mening ismim Thread-8 Men mavzu! Mening ismim Thread-9 Men mavzu! Mening ismim Thread-7 Uchinchi konsol chiqishi: Men Threadman! Mening ismim Thread-0 Men mavzu! Mening ismim Thread-3 Men mavzu! Mening ismim Thread-1 Men mavzu! Mening ismim Thread-2 Men mavzu! Mening ismim Thread-6 Men mavzu! Mening ismim Thread-4 Men mavzu! Mening ismim Thread-9 Men mavzu! Mening ismim Thread-5 Men mavzu! Mening ismim Thread-7 Men mavzu! Mening ismim Thread-8
Ko'p ish zarralarini yaratish muammolari
Kitoblar misolida siz ko'p ish zarralari juda muhim muammolarni hal qilishini va undan foydalanish dasturlarimiz ishini tezlashtirishini ko'rdingiz. Ko'p hollarda - ko'p marta. Ammo ko'p ish zarralarini o'tkazish murakkab mavzu deb hisoblanishi bejiz emas. Axir, noto'g'ri ishlatilsa, ularni hal qilish o'rniga muammolarni keltirib chiqaradi. Men "muammolar yaratish" deganimda, men mavhum narsani nazarda tutmayman. Ko'p ish zarralari sabab bo'lishi mumkin bo'lgan ikkita o'ziga xos muammo mavjud: tugash va poyga holati. Tugallanish - bu bir nechta oqimlar bir-biri bilan band bo'lgan resurslarni kutayotgan va ularning hech biri ishlashni davom ettira olmaydigan holat. Kelgusi ma'ruzalarda bu haqda ko'proq gaplashamiz, ammo hozircha bu misol etarli bo'ladi: Tasavvur qiling-a, thread-1 qandaydir Ob'ekt-1 bilan ishlayapti va thread-2 Ob'ekt-2 bilan ishlayapti. Dastur quyidagicha yozilgan:- Thread-1 ob'ekt-1 bilan ishlashni to'xtatadi va Thread-2 2-ob'ekt bilan ishlashni to'xtatib, Ob'ekt-1ga o'tishi bilanoq Ob'ekt-2 ga o'tadi.
- Thread-1 1-ob'ekt bilan ishlashni to'xtatib, Ob'ekt-2 ga o'tish bilanoq, Thread-2 Ob'ekt-2 bilan ishlashni to'xtatadi va Ob'ekt-1 ga o'tadi.
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();
}
}
}
Endi tasavvur qiling-a, dastur oziq-ovqat tayyorlaydigan robotning ishlashi uchun javobgardir! Thread-0 tuxumni muzlatgichdan oladi. Stream 1 pechkani yoqadi. Stream-2 qovurilgan idishni olib, pechka ustiga qo'yadi. 3-oqim pechkada olov yoqadi. Stream 4 skovorodkaga yog' quying. Stream 5 tuxumni sindirib, ularni qovurilgan idishga quyadi. Stream 6 chig'anoqlarni axlat qutisiga tashlaydi. Stream-7 tayyor omletni issiqdan olib tashlaydi. Potok-8 omletni plastinka ustiga qo'yadi. Stream-9 idishlarni yuvadi. Dasturimiz natijalarini ko'ring: Thread-0 bajarildi Mavzu-2 bajarildi Mavzu-1 mavzu bajarildi Mavzu-4 mavzu bajarildi Mavzu-9 mavzu bajarildi Mavzu-5 mavzu bajarildi. ip bajarildi -3 Thread-6 ip bajarildi. Skript qiziqarlimi? :) Va barchasi, chunki bizning dasturimizning ishlashi iplarning bajarilish tartibiga bog'liq. Ketma-ketlikning eng kichik buzilishi bilan bizning oshxonamiz do'zaxga aylanadi va aqldan ozgan robot uning atrofidagi hamma narsani yo'q qiladi. Bu, shuningdek, ko'p bosqichli dasturlashda keng tarqalgan muammo bo'lib, siz bu haqda bir necha marta eshitasiz. Ma'ruza yakunida men sizga multithreading bo'yicha kitobni tavsiya qilmoqchiman.
GO TO FULL VERSION