CodeGym /Java Blog /Random /Multithreading sa Java
John Squirrels
Antas
San Francisco

Multithreading sa Java

Nai-publish sa grupo
Hi! Una sa lahat, binabati kita: naabot mo na ang paksa ng Multithreading sa Java! Isa itong seryosong tagumpay — malayo na ang narating mo. Ngunit ihanda ang iyong sarili: isa ito sa pinakamahirap na paksa sa kurso. At hindi dahil gumagamit kami ng mga kumplikadong klase o maraming pamamaraan dito: sa katunayan, gagamit kami ng mas mababa sa dalawampu. Ito ay higit pa na kakailanganin mong baguhin nang bahagya ang iyong pag-iisip. Dati, ang iyong mga programa ay naisakatuparan nang sunud-sunod. Ang ilang mga linya ng code ay sumunod sa iba, ang ilang mga pamamaraan ay sumunod sa iba, at ang lahat ay karaniwang malinaw. Una, kinakalkula namin ang isang bagay, pagkatapos ay ipinakita ang resulta sa console, at pagkatapos ay natapos ang programa. Upang maunawaan ang multithreading, mas mahusay na mag-isip sa mga tuntunin ng paralelismo. Magsimula tayo sa isang bagay na medyo simple: ) Isipin na ang iyong pamilya ay lumilipat mula sa isang bahay patungo sa isa pa. Ang pagtitipon ng lahat ng iyong mga libro ay magiging isang mahalagang bahagi ng paglipat. Nakaipon ka ng maraming libro, at kailangan mong ilagay ang mga ito sa mga kahon. Sa kasalukuyan, ikaw lang ang available. Si nanay ay naghahanda ng pagkain, si kuya ay nag-iimpake ng mga damit, at si ate ay pumunta sa tindahan. Mag-isa, kaya mong pamahalaan kahit papaano. Maaga o huli, ikaw mismo ang kukumpleto sa gawain, ngunit aabutin ito ng maraming oras. Gayunpaman, babalik ang iyong kapatid na babae mula sa tindahan sa loob ng 20 minuto, at wala na siyang ibang gagawin. Para makasama ka niya. Ang gawain ay hindi nagbago: ilagay ang mga libro sa mga kahon. Ngunit ito ay ginaganap nang dalawang beses nang mas mabilis. Bakit? Dahil ang trabaho ay nangyayari sa parallel. Dalawang magkaibang 'thread' (ikaw at ang iyong kapatid na babae) ay gumaganap ng parehong gawain nang sabay-sabay. At kung walang magbabago, pagkatapos ay magkakaroon ng malaking pagkakaiba sa oras kumpara sa sitwasyon kung saan gagawin mo ang lahat nang mag-isa. Kung tatapusin ni kuya ang kanyang trabaho sa lalong madaling panahon, matutulungan ka niya at magiging mas mabilis ang mga bagay-bagay.

Ang mga problema ay nalutas sa pamamagitan ng multithreading

Ang multithreading ay aktwal na naimbento upang makamit ang dalawang mahahalagang layunin:
  1. Gumawa ng ilang bagay nang sabay-sabay.

    Sa halimbawa sa itaas, ang iba't ibang mga thread (mga miyembro ng pamilya) ay nagsagawa ng ilang mga aksyon nang magkatulad: naghugas sila ng mga pinggan, nagpunta sa tindahan, at nag-impake ng mga bagay.

    Maaari kaming mag-alok ng isang halimbawa na mas malapit na nauugnay sa programming. Ipagpalagay na mayroon kang isang programa na may isang user interface. Kapag na-click mo ang 'Magpatuloy' sa programa, dapat mangyari ang ilang kalkulasyon at dapat makita ng user ang sumusunod na screen. Kung ang mga pagkilos na ito ay isinagawa nang sunud-sunod, ang program ay mag-hang lamang pagkatapos na i-click ng user ang pindutang 'Magpatuloy'. Makikita ng user ang screen na may screen na button na 'Magpatuloy' hanggang sa maisagawa ng program ang lahat ng panloob na kalkulasyon at maabot ang bahagi kung saan nire-refresh ang user interface.

    Well, sa palagay ko maghihintay tayo ng ilang minuto!

    Multithreading sa Java: kung ano ito, ang mga benepisyo nito at karaniwang mga pitfalls - 3

    O maaari naming gawin muli ang aming programa, o, gaya ng sinasabi ng mga programmer, 'iparallelize' ito. Gawin natin ang ating mga kalkulasyon sa isang thread at iguhit ang user interface sa isa pa. Karamihan sa mga computer ay may sapat na mapagkukunan upang gawin ito. Kung tatahakin natin ang rutang ito, hindi mag-freeze ang program at ang user ay lilipat nang maayos sa pagitan ng mga screen nang hindi nababahala tungkol sa kung ano ang nangyayari sa loob. Ang isa ay hindi nakikialam sa isa pa :)

  2. Magsagawa ng mga kalkulasyon nang mas mabilis.

    Ang lahat ay mas simple dito. Kung ang aming processor ay maraming core, at karamihan sa mga processor ngayon ay mayroon, kung gayon ang ilang mga core ay maaaring humawak sa aming listahan ng mga gawain nang magkatulad. Malinaw, kung kailangan nating magsagawa ng 1000 na gawain at ang bawat isa ay tumatagal ng isang segundo, maaaring tapusin ng isang core ang listahan sa loob ng 1000 segundo, dalawang core sa loob ng 500 segundo, tatlo sa mahigit 333 segundo, atbp.

Ngunit tulad ng nabasa mo na sa araling ito, ang mga sistema ngayon ay napakatalino, at sa kahit isang computing core ay nakakamit ang parallelism, o sa halip ay pseudo-parallelism, kung saan ang mga gawain ay ginagawa nang halili. Ilipat natin ang mga pangkalahatan sa mga detalye at kilalanin ang pinakamahalagang klase sa Java multithreading library — java.lang.Thread. Sa mahigpit na pagsasalita, ang mga thread ng Java ay kinakatawan ng mga pagkakataon ng klase ng Thread . Nangangahulugan ito na para gumawa at magpatakbo ng 10 thread, kailangan mo ng 10 instance 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 magpatakbo ng mga thread, kailangan nating lumikha ng isang klase, gawin itong magmana ng java.lang . Thread class, at i-override ang run() method nito. Ang huling pangangailangan na iyon ay napakahalaga. Nasa run() na paraan kung saan tinutukoy namin ang lohika para sa aming thread na isakatuparan. Ngayon, kung gagawa tayo at magpapatakbo ng isang instance ng MyFirstThread , ang run() na paraan ay magpapakita ng linyang may pangalan: ang getName() method ay nagpapakita ng pangalan ng 'system' ng thread, na awtomatikong itinalaga. Ngunit bakit tayo ay nagsasalita nang pansamantala? Gumawa tayo ng isa at alamin!

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 Gumawa tayo ng 10 thread ( MyFirstThread objects, which inherit Thread ) at simulan ang mga ito sa pamamagitan ng pagtawag sa start() method sa bawat object. Pagkatapos tawagan ang start() na paraan, ang logic sa run() na paraan ay ipapatupad. Tandaan: ang mga pangalan ng thread ay hindi maayos. Kakaiba na hindi sila sunod-sunod:, Thread-1 , Thread-2 , at iba pa? Habang nangyayari ito, ito ay isang halimbawa ng isang oras kung kailan hindi akma ang 'sequential' na pag-iisip. Ang isyu ay nagbigay lang kami ng mga command para gumawa at magpatakbo ng 10 thread. Ang thread scheduler, isang espesyal na mekanismo ng operating system, ang nagpapasya sa kanilang execution order. Ang tumpak na disenyo nito at diskarte sa paggawa ng desisyon ay mga paksa para sa isang malalim na talakayan na hindi natin susuriin sa ngayon. Ang pangunahing bagay na dapat tandaan ay hindi makokontrol ng programmer ang pagkakasunud-sunod ng pagpapatupad ng mga thread. Upang maunawaan ang kabigatan ng sitwasyon, subukang patakbuhin ang main() na pamamaraan sa halimbawa sa itaas nang ilang beses. Output ng console sa pangalawang pagtakbo: Thread ako! 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 Console na output mula sa ikatlong run: 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 nilikha ng multithreading

Sa aming halimbawa sa mga aklat, nakita mo na nalulutas ng multithreading ang mga napakahalagang gawain at maaaring gawing mas mabilis ang aming mga programa. Kadalasan maraming beses na mas mabilis. Ngunit ang multithreading ay itinuturing na isang mahirap na paksa. Sa katunayan, kung ginamit nang hindi wasto, lumilikha ito ng mga problema sa halip na lutasin ang mga ito. Kapag sinabi kong 'lumilikha ng mga problema', hindi ko ibig sabihin sa ilang abstract na kahulugan. Mayroong dalawang partikular na problema na maaaring lumikha ng multithreading: deadlock at mga kondisyon ng lahi. Ang deadlock ay isang sitwasyon kung saan maraming mga thread ang naghihintay para sa mga mapagkukunang hawak ng bawat isa, at wala sa mga ito ang maaaring magpatuloy na tumakbo. Pag-uusapan pa natin ito sa mga susunod na aralin. Ang sumusunod na halimbawa ay sapat na sa ngayon: Multithreading sa Java: kung ano ito, mga benepisyo nito at karaniwang mga pitfalls - 4Isipin na ang Thread-1 ay nakikipag-ugnayan sa ilang Object-1, at ang Thread-2 ay nakikipag-ugnayan sa Object-2. Higit pa rito, isinulat ang programa upang:
  1. Ang Thread-1 ay humihinto sa pakikipag-ugnayan sa Object-1 at lumipat sa Object-2 sa sandaling huminto ang Thread-2 sa pakikipag-ugnayan sa Object-2 at lumipat sa Object-1.
  2. Ang Thread-2 ay humihinto sa pakikipag-ugnayan sa Object-2 at lumipat sa Object-1 sa sandaling huminto ang Thread-1 sa pakikipag-ugnayan sa Object-1 at lumipat sa Object-2.
Kahit na walang malalim na pag-unawa sa multithreading, madali mong makikita na walang mangyayari. Ang mga thread ay hindi kailanman magpapalit ng lugar at maghihintay sa isa't isa magpakailanman. Ang pagkakamali ay tila halata, ngunit sa katotohanan ay hindi. Madali mong magagawa ito sa isang programa. Isasaalang-alang namin ang mga halimbawa ng code na nagdudulot ng deadlock sa mga susunod na aralin. Siyanga pala, ang Quora ay may magandang halimbawa sa totoong buhay na nagpapaliwanag kung ano ang deadlockay. 'Sa ilang mga estado sa India, hindi ka nila ibebenta ng lupang pang-agrikultura maliban kung ikaw ay isang rehistradong magsasaka. Gayunpaman, hindi ka nila irerehistro bilang isang magsasaka kung hindi ka nagmamay-ari ng lupang pang-agrikultura'. Malaki! Anong masasabi natin?! :) Ngayon ay pag-usapan natin ang tungkol sa mga kondisyon ng lahi. Ang kundisyon ng lahi ay isang error sa disenyo sa isang multithreaded system o application, kung saan ang pagpapatakbo ng system o application ay depende sa pagkakasunud-sunod kung saan ang mga bahagi ng code ay isinasagawa. Tandaan, ang aming halimbawa kung saan kami nagsimula ng mga thread:

public class MyFirstThread extends Thread {

   @Override
   public void run() {
       System.out.println("Thread executed: " + 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 may pananagutan sa pagpapatakbo ng isang robot na nagluluto ng pagkain! Ang thread-0 ay kumukuha ng mga itlog mula sa refrigerator. Binubuksan ng thread-1 ang kalan. Kumuha ng kawali ang Thread-2 at inilalagay ito sa kalan. Sinisindi ng thread-3 ang kalan. Ang thread-4 ay nagbubuhos ng langis sa kawali. Binasag ng thread-5 ang mga itlog at ibinuhos sa kawali. Ang Thread-6 ay nagtatapon ng mga kabibi sa basurahan. Tinatanggal ng thread-7 ang mga nilutong itlog mula sa burner. Inilalagay ng thread-8 ang mga nilutong itlog sa isang plato. Ang thread-9 ay naghuhugas ng pinggan. Tingnan ang mga resulta ng aming programa: Thread executed: Thread-0 Thread executed: Thread-2 Thread executed Thread-1 Thread executed: Thread-4 Thread executed: Thread-9 Thread executed: Thread-5 Thread executed: Thread-8 Thread naisakatuparan: Thread-7 Thread na naisakatuparan: Thread-3 Ito ba ay isang comedy routine? :) At lahat dahil ang gawain ng aming programa ay nakasalalay sa pagkakasunud-sunod ng pagpapatupad ng mga thread. Dahil sa kaunting paglabag sa kinakailangang pagkakasunod-sunod, nagiging impiyerno ang aming kusina, at sinisira ng isang nakakabaliw na robot ang lahat sa paligid nito. Ito rin ay isang karaniwang problema sa multithreaded programming. Maririnig mo ang tungkol dito nang higit sa isang beses. Sa pagtatapos ng araling ito, nais kong magrekomenda ng aklat tungkol sa multithreading. Multithreading sa Java: kung ano ito, mga benepisyo nito at karaniwang mga pitfalls - 6Ang 'Java Concurrency in Practice' ay isinulat noong 2006, ngunit hindi nawala ang kaugnayan nito. Ito ay nakatuon sa multithreaded Java programming — mula sa mga pangunahing kaalaman hanggang sa pinakakaraniwang pagkakamali at antipattern. Kung balang araw ay magpasya kang maging isang multithreading guru, ang aklat na ito ay dapat basahin. Magkita-kita tayo sa susunod na mga aralin! :)
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION