Mga problemang nalulutas ng multithreading sa Java
Mahalaga, ang Java multithreading ay naimbento upang malutas ang dalawang pangunahing problema:-
Magsagawa ng maraming pagkilos nang sabay-sabay.
Sa halimbawa sa itaas, ang iba't ibang mga thread (i.e. mga miyembro ng pamilya) ay nagsagawa ng ilang mga aksyon nang magkatulad: naghugas ng mga pinggan, pumunta sa tindahan, nagtupi ng mga bagay.
Ang isang mas "programmer" na halimbawa ay maaaring ibigay. Isipin na mayroon kang program na may user interface. Kapag na-click ang button na Magpatuloy, dapat mangyari ang ilang kalkulasyon sa loob ng programa, at dapat makita ng user ang sumusunod na screen ng interface. Kung ang mga pagkilos na ito ay isinasagawa nang sunud-sunod, pagkatapos ng pag-click sa pindutang "Magpatuloy", ang programa ay mag-freeze lamang. Makikita ng user ang parehong screen na may button na "Magpatuloy" hanggang sa makumpleto ang lahat ng panloob na kalkulasyon at maabot ng programa ang bahagi kung saan magsisimulang iguhit ang interface.
Well, maghintay tayo ng ilang minuto!
Maaari rin naming gawing muli ang aming programa, o, gaya ng sinasabi ng mga programmer, "magparallelize." Hayaang maisagawa ang mga kinakailangang kalkulasyon sa isang thread, at pag-render ng interface sa isa pa. Karamihan sa mga computer ay may sapat na mapagkukunan para dito. Sa kasong ito, ang programa ay hindi magiging "hangal", at ang gumagamit ay mahinahon na lumipat sa pagitan ng mga screen ng interface nang hindi nababahala tungkol sa kung ano ang nangyayari sa loob. Hindi ito nakikialam :)
-
Pabilisin ang mga kalkulasyon.
Ang lahat ay mas simple dito. Kung ang aming processor ay may ilang mga core, at karamihan sa mga processor ay multi-core na ngayon, ang aming listahan ng mga gawain ay maaaring malutas nang magkatulad sa pamamagitan ng ilang mga core. Malinaw, kung kailangan nating lutasin ang 1000 mga problema at ang bawat isa sa kanila ay malulutas sa isang segundo, isang core ang makakayanan ang listahan sa loob ng 1000 segundo, dalawang core sa loob ng 500 segundo, tatlo sa loob lamang ng 333 segundo, at iba pa.
Thread
. Iyon ay, upang lumikha at magpatakbo ng 10 mga thread, kakailanganin mo ng 10 mga bagay ng klase na ito. Isulat natin ang pinakasimpleng halimbawa:
public class MyFirstThread extends Thread {
@Override
public void run() {
System.out.println("I'm Thread! My name is " + getName());
}
}
Upang lumikha at maglunsad ng mga thread, kailangan nating lumikha ng isang klase at magmana nito mula sa java.lang
. Thread
at i-override ang pamamaraan sa loob nito run()
. Ang huli ay napakahalaga. Ito ay sa pamamaraan na run()
inireseta namin ang lohika na dapat isagawa ng aming thread. Ngayon, kung gagawa kami ng isang instance MyFirstThread
at patakbuhin ito, ang pamamaraan run()
ay magpi-print ng isang linya na may pangalan nito sa console: ang pamamaraan getName()
ay nagpi-print ng pangalan ng "system" ng thread, na awtomatikong itinalaga. Bagaman, sa totoo lang, bakit "kung"? Gumawa tayo at subukan!
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
MyFirstThread thread = new MyFirstThread();
thread.start();
}
}
}
Output ng console: Ako ay Thread! Ang pangalan ko ay Thread-2 Ako ay Thread! Ang pangalan ko ay Thread-1 Ako ay Thread! Ang pangalan ko ay Thread-0 Ako ay Thread! Ang pangalan ko ay Thread-3 Ako ay Thread! Ang pangalan ko ay Thread-6 Ako ay Thread! Ang pangalan ko ay Thread-7 Ako ay Thread! Ang pangalan ko ay Thread-4 Ako ay Thread! Ang pangalan ko ay Thread-5 Ako ay Thread! Ang pangalan ko ay Thread-9 Ako ay Thread! Ang pangalan ko ay Thread-8 Gumagawa kami ng 10 mga thread (mga bagay) MyFirstThread
na nagmana mula sa Thread
at naglulunsad ng mga ito sa pamamagitan ng pagtawag sa pamamaraan ng object start()
. Pagkatapos tumawag sa isang pamamaraan , start()
ang pamamaraan nito ay magsisimulang gumana run()
, at ang lohika na nakasulat dito ay naisakatuparan. Pakitandaan: ang mga pangalan ng thread ay hindi maayos. Ito ay medyo kakaiba, bakit hindi sila pinatay sa turn: Thread-0
, Thread-1
, Thread-2
at iba pa? Ito ay eksaktong isang halimbawa kung kailan hindi gagana ang karaniwang, "sequential" na pag-iisip. Ang katotohanan ay sa kasong ito ay naglalabas lamang kami ng mga utos upang lumikha at maglunsad ng 10 mga thread. Sa anong pagkakasunud-sunod na dapat silang ilunsad ay napagpasyahan ng thread scheduler: isang espesyal na mekanismo sa loob ng operating system. Napakakomplikadong paksa kung gaano ito nakabalangkas at sa kung anong prinsipyo ito gumagawa ng mga desisyon, at hindi na natin ito sasabak ngayon. Ang pangunahing bagay na dapat tandaan ay hindi makokontrol ng programmer ang pagkakasunud-sunod ng pagpapatupad ng thread. Upang mapagtanto ang kabigatan ng sitwasyon, subukang patakbuhin ang pamamaraan main()
mula sa halimbawa sa itaas nang ilang beses. Pangalawang console output: Ako ay Thread! Ang pangalan ko ay Thread-0 Ako ay Thread! Ang pangalan ko ay Thread-4 Ako ay Thread! Ang pangalan ko ay Thread-3 Ako ay Thread! Ang pangalan ko ay Thread-2 Ako ay Thread! Ang pangalan ko ay Thread-1 Ako ay Thread! Ang pangalan ko ay Thread-5 Ako ay Thread! Ang pangalan ko ay Thread-6 Ako ay Thread! Ang pangalan ko ay Thread-8 Ako ay Thread! Ang pangalan ko ay Thread-9 Ako ay Thread! Ang pangalan ko ay Thread-7 Third console output: Ako ay Thread! Ang pangalan ko ay Thread-0 Ako ay Thread! Ang pangalan ko ay Thread-3 Ako ay Thread! Ang pangalan ko ay Thread-1 Ako ay Thread! Ang pangalan ko ay Thread-2 Ako ay Thread! Ang pangalan ko ay Thread-6 Ako ay Thread! Ang pangalan ko ay Thread-4 Ako ay Thread! Ang pangalan ko ay Thread-9 Ako ay Thread! Ang pangalan ko ay Thread-5 Ako ay Thread! Ang pangalan ko ay Thread-7 Ako ay Thread! Ang pangalan ko ay Thread-8
Mga problemang nalilikha ng multithreading
Sa halimbawa sa mga aklat, nakita mo na ang multithreading ay nalulutas ang mga mahahalagang problema, at ang paggamit nito ay nagpapabilis sa gawain ng aming mga programa. Sa maraming kaso - maraming beses. Ngunit hindi para sa wala na ang multithreading ay itinuturing na isang kumplikadong paksa. Pagkatapos ng lahat, kung ginamit nang hindi tama, lumilikha ito ng mga problema sa halip na lutasin ang mga ito. Kapag sinabi kong "lumikha ng mga problema," hindi abstract ang ibig kong sabihin. Mayroong dalawang partikular na problema na maaaring idulot ng multithreading: deadlock at kundisyon ng lahi. Ang deadlock ay isang sitwasyon kung saan maraming mga thread ang naghihintay para sa mga mapagkukunan na inookupahan ng bawat isa, at wala sa mga ito ang maaaring magpatuloy sa pagpapatupad. Pag-uusapan natin ang higit pa tungkol dito sa mga lektura sa hinaharap, ngunit sa ngayon ay sapat na ang halimbawang ito: Isipin na ang thread-1 ay gumagana sa ilang Object-1, at ang thread-2 ay gumagana sa Object-2. Ang programa ay nakasulat tulad nito:- Hihinto sa pagtatrabaho ang Thread-1 sa Object-1 at lilipat sa Object-2 sa sandaling huminto ang Thread-2 sa Object 2 at lumipat sa Object-1.
- Hihinto sa pagtatrabaho ang Thread-2 sa Object-2 at lilipat sa Object-1 sa sandaling huminto ang Thread-1 sa Object 1 at lumipat sa Object-2.
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();
}
}
}
Ngayon isipin na ang programa ay responsable para sa pagpapatakbo ng isang robot na naghahanda ng pagkain! Inilalabas ng Thread-0 ang mga itlog sa refrigerator. Binubuksan ng Stream 1 ang kalan. Ang Stream-2 ay kumuha ng kawali at inilalagay ito sa kalan. Ang Stream 3 ay nagsisindi ng apoy sa kalan. Ang Stream 4 ay nagbubuhos ng mantika sa kawali. Binabasag ng Stream 5 ang mga itlog at ibinuhos sa kawali. Ang Stream 6 ay nagtatapon ng mga shell sa basurahan. Tinatanggal ng Stream-7 ang natapos na piniritong itlog mula sa init. Ang Potok-8 ay naglalagay ng piniritong itlog sa isang plato. Naghuhugas ng pinggan ang Stream-9. Tingnan ang mga resulta ng aming programa: Thread-0 executed Thread-2 thread executed Thread-1 thread executed Thread-4 thread executed Thread-9 thread executed Thread-5 thread executed Thread-8 thread executed Thread-7 thread executed Thread-7 thread executed -3 Thread-6 thread executed. Masaya ba ang script? :) At lahat dahil ang pagpapatakbo ng aming programa ay nakasalalay sa pagkakasunud-sunod kung saan ang mga thread ay naisakatuparan. Sa kaunting paglabag sa pagkakasunud-sunod, nagiging impiyerno ang aming kusina, at sinisira ng isang robot ang lahat sa paligid nito. Isa rin itong karaniwang problema sa multithreaded programming, na maririnig mo nang higit sa isang beses. Sa pagtatapos ng lektura, nais kong irekomenda sa iyo ang isang libro sa multithreading.
GO TO FULL VERSION