Navoja se nanaša na prakso sočasnega izvajanja programskih procesov za izboljšanje učinkovitosti aplikacije. Čeprav ni tako pogosto delati z nitmi neposredno v poslovnih aplikacijah, jih ves čas uporabljajo v okoljih Java.
Kot primer, ogrodja, ki obdelujejo velik obseg informacij, na primer Spring Batch, uporabljajo niti za upravljanje podatkov. Sočasno upravljanje niti ali procesorjev izboljšuje zmogljivost, kar ima za posledico hitrejše in učinkovitejše programe.
Pridobite izvorno kodo
Pridobite kodo za ta Java Challenger. Med sledenjem primerom lahko izvajate lastne teste.
Poiščite svojo prvo nit: glavna () metoda Java
Tudi če nikoli niste delali neposredno z nitmi Java, ste posredno delali z njimi, ker metoda Java (main) vsebuje glavno nit. Kadar koli izvedete glavni ()
metodo, izvedli ste tudi glavno Navoj
.
Preučevanje Navoj
class je zelo koristen za razumevanje, kako Threading deluje v programih Java. Do niti, ki se izvaja, lahko dostopamo s klicem currentThread (). getName ()
metoda, kot je prikazano tukaj:
javni razred MainThread {javna statična void main (String ... mainThread) {System.out.println (Thread.currentThread (). getName ()); }}
Ta koda bo natisnila "main" in identificirala nit, ki se trenutno izvaja. Vedeti, kako prepoznati nit, ki se izvaja, je prvi korak k absorpciji konceptov niti.
Življenjski cikel niti Java
Pri delu z nitmi je ključnega pomena, da se zavedate stanja niti. Življenjski cikel niti Java je sestavljen iz šestih stanj niti:
- Novo: Novo
Nit ()
je bil instanciran. - Teče: The
Navoj
jezačetek ()
je bila uporabljena metoda. - Tek: The
začetek ()
je bila priklicana metoda in nit se izvaja. - Suspended: Nit je začasno prekinjena in jo lahko nadaljuje druga nit.
- Blokirano: Nit čaka na priložnost za zagon. To se zgodi, ko je ena nit že priklicala
sinhronizirano ()
in naslednja nit mora počakati, dokler ni končana. - Prenehala: Izvajanje niti je končano.
O stanju niti je treba raziskati in razumeti več, vendar so informacije na sliki 1 dovolj, da lahko rešite ta izziv Java.
Sočasna obdelava: razširitev razreda Thread
Najenostavnejša, sočasna obdelava se izvede z razširitvijo a Navoj
razred, kot je prikazano spodaj.
javni razred InheritingThread razširja Thread {InheritingThread (String threadName) {super (threadName); } javna statična void glavna (String ... dedovanje) {System.out.println (Thread.currentThread (). getName () + "teče"); novo InheritingThread ("nasledstvoThread"). start (); } @Override public void run () {System.out.println (Thread.currentThread (). GetName () + "teče"); }}
Tukaj izvajamo dve niti: MainThread
in InheritingThread
. Ko prikličemo začetek ()
metoda z novo inheritingThread ()
, logika v teči ()
metoda se izvede.
V datoteko. Tudi prenesemo ime druge niti Navoj
class constructor, tako da bo rezultat:
main teče. inheritingThread se izvaja.
Runnable vmesnik
Namesto da bi uporabljali dedovanje, bi lahko implementirali vmesnik Runnable. Mimo Teče
znotraj a Navoj
konstruktorja povzroči manjše spenjanje in večjo prilagodljivost. Po prehodu Teče
, lahko pokličemo začetek ()
metoda natančno tako kot v prejšnjem primeru:
javni razred RunnableThread implementira Runnable {public static void main (String ... runnableThread) {System.out.println (Thread.currentThread (). getName ()); nova nit (nova RunnableThread ()). start (); } @Override public void run () {System.out.println (Thread.currentThread (). GetName ()); }}
Ne-daemon vs daemon niti
Glede izvedbe obstajata dve vrsti niti:
- Nedemonske niti se izvajajo do konca. Glavna nit je dober primer niti, ki ni demon. Koda v
glavni ()
se bo vedno izvajala do konca, razen če aSystem.exit ()
prisili program, da se dokonča. - A nit demona je nasprotno, v bistvu postopek, ki ga ni treba izvesti do konca.
Zapomni si pravilo: Če se ograjena nit brez demona konča pred nitjo demona, se nit demona ne bo izvedla do konca.
Če želite bolje razumeti razmerje niti demona in nedemona, preučite ta primer:
uvoz java.util.stream.IntStream; javni razred NonDaemonAndDaemonThread {javna statična void main (String ... nonDaemonAndDaemon) vrže InterruptedException {System.out.println ("Zagon izvajanja v niti" + Thread.currentThread (). getName ()); Nit daemonThread = nova nit (() -> IntStream.rangeClosed (1, 100000) .forEach (System.out :: println)); daemonThread.setDaemon (true); daemonThread.start (); Navoj.spanje (10); System.out.println ("Konec izvedbe v niti" + Thread.currentThread (). GetName ()); }}
V tem primeru sem z nitjo demona prijavil obseg od 1 do 100.000, jih vse ponovil in nato natisnil. Ampak ne pozabite, da nit demona ne bo dokončala izvedbe, če se glavna nit ne-demona konča najprej.
Izhod se bo nadaljeval na naslednji način:
- Začetek izvajanja v glavni niti.
- Natisnite številke od 1 do 100.000.
- Konec izvedbe v glavni niti, zelo verjetno pred ponovitvijo do 100.000 dokončanih.
Končni rezultat bo odvisen od vaše izvedbe JVM.
In to me pripelje do naslednje točke: niti so nepredvidljive.
Prednost niti in JVM
Izvedbo niti je mogoče dati prednost kot setPriority
metoda, vendar je način obdelave odvisen od izvedbe JVM. Linux, MacOS in Windows imajo različne izvedbe JVM in vsak bo obravnaval prednost niti v skladu s svojimi privzetimi nastavitvami.
Prednost niti, ki jo nastavite, pa vpliva na vrstni red priklica niti. Tri konstante, navedene v Navoj
razred so:
/ ** * Najmanjša prednost, ki jo lahko ima nit. * / javni statični končni int MIN_PRIORITY = 1; / ** * Privzeta prednost, ki je dodeljena niti. * / javni statični končni int NORM_PRIORITY = 5; / ** * Največja prednost, ki jo lahko ima nit. * / javni statični končni int MAX_PRIORITY = 10;
Poskusite zagnati nekaj preskusov na naslednji kodi, da vidite, s katero prednostjo izvajanja ste končali:
javni razred ThreadPriority {javna statična void main (String ... threadPriority) {Thread moeThread = new Thread (() -> System.out.println ("Moe")); Nit barneyThread = nova nit (() -> System.out.println ("Barney")); Nit homerThread = nova nit (() -> System.out.println ("Homer")); moeThread.setPriority (Thread.MAX_PRIORITY); barneyThread.setPriority (Thread.NORM_PRIORITY); homerThread.setPriority (Thread.MIN_PRIORITY); homerThread.start (); barneyThread.start (); moeThread.start (); }}
Tudi če nastavimo moeThread
kot MAX_PRIORITY
, ne moremo računati, da bo ta nit izvedena prva. Namesto tega bo vrstni red izvršitve naključen.
Konstante v primerjavi s števili
The Navoj
razred je bil uveden z Javo 1.0. Takrat so bile prioritete določene s konstantami in ne s števili. Težava pa je pri uporabi konstant: če prenesemo prednostno številko, ki ni v območju od 1 do 10, setPriority ()
metoda vrže IllegalArgumentException. Danes lahko z enumom zaobidemo to težavo. Uporaba enumov onemogoča posredovanje nezakonitega argumenta, kar poenostavlja kodo in nam daje večji nadzor nad njenim izvajanjem.
Sprejmite izziv Java niti!
Le malo ste se naučili o nitih, vendar je to dovolj za izziv Java v tej objavi.
Za začetek preučite naslednjo kodo:
javni razred ThreadChallenge {private static int wolverineAdrenaline = 10; public static void main (String ... doYourBest) {new Motorcycle ("Harley Davidson"). start (); Motorcycle fastBike = nov motocikel ("Dodge Tomahawk"); fastBike.setPriority (Thread.MAX_PRIORITY); fastBike.setDaemon (false); fastBike.start (); Motocikel yamaha = nov motocikel ("Yamaha YZF"); yamaha.setPriority (nit.MIN_PRIORITY); yamaha.start (); } statični razred Motorcycle razširja nit {Motorcycle (String bikeName) {super (bikeName); } @Override public void run () {wolverineAdrenaline ++; if (wolverineAdrenaline == 13) {System.out.println (this.getName ()); }}}}
Kakšen bo izhod te kode? Analizirajte kodo in poskusite sami določiti odgovor na podlagi tega, kar ste se naučili.
A. Harley Davidson
B. Dodge Tomahawk
C. Yamaha YZF
D. Nedoločen
Kaj se je pravkar zgodilo? Razumevanje vedenja niti
V zgornji kodi smo ustvarili tri niti. Prva nit je Harley Davidson
in tej niti smo dodelili privzeto prednost. Druga nit je Dodge Tomahawk
, dodeljena MAX_PRIORITY
. Tretji je Yamaha YZF
, s MIN_PRIORITY
. Nato smo začeli niti.
Če želite določiti vrstni red izvajanja niti, boste morda najprej opazili, da Motorno kolo
razred podaljša Navoj
razreda in da smo v konstruktorju predali ime niti. Prav tako smo preglasili teči ()
metoda s pogojem: če je wolverineAdrenalin enak 13
.
Čeprav Yamaha YZF
je tretja nit v našem vrstnem redu izvedbe in ima MIN_PRIORITY
ni nobenega zagotovila, da bo izveden zadnji za vse izvedbe JVM.
Opazili boste tudi, da smo v tem primeru nastavili Dodge Tomahawk
nit kot demon
. Ker gre za nit demona, Dodge Tomahawk
morda nikoli ne dokonča izvršitve. Toda drugi dve niti privzeto nista demona, zato Harley Davidson
in Yamaha YZF
niti bodo zagotovo dokončale njihovo izvedbo.
Za zaključek bo rezultat D: Nedoločen, ker ni nobenega zagotovila, da bo načrtovalnik niti upošteval naš vrstni red izvajanja ali prioritet nit.
Ne pozabite, da se ne moremo zanašati na programsko logiko (vrstni red niti ali prednost niti) za napovedovanje vrstnega reda izvajanja JVM.
Video izziv! Razhroščevanje argumentov spremenljivk
Odpravljanje napak je eden najlažjih načinov za popolno absorpcijo konceptov programiranja, hkrati pa izboljšate kodo. V tem videoposnetku lahko sledite, medtem ko odpravljam napake in razlagam izziv vedenja niti:
Pogoste napake z nitmi Java
- Klicanje na
teči ()
, da poskusite zagnati novo nit. - Dvakrat poskusite zagnati nit (to bo povzročilo
IllegalThreadStateException
). - Omogočanje več procesov spreminjanju stanja predmeta, ko se ta ne bi smel spremeniti.
- Pisanje programske logike, ki temelji na prioriteti niti (ne morete jo predvideti).
- Zanašanje na vrstni red izvajanja niti - tudi če nit začnemo najprej, ni zagotovila, da bo najprej izvedena.
Kaj si je treba zapomniti pri nitih Java
- Prikliči
začetek ()
metoda za zagon aNavoj
. - Možno je podaljšati
Navoj
razred neposredno za uporabo niti. - Dejanje niti je mogoče izvesti znotraj a
Teče
vmesnik. - Prednost niti je odvisna od izvedbe JVM.
- Obnašanje niti bo vedno odvisno od izvedbe JVM.
- Nit demona se ne bo dokončala, če se zaprta nit, ki ni demon, konča najprej.
Preberite več o nitih Java na JavaWorldu
- Preberite serijo niti 101 Java, če želite izvedeti več o nitih in izvedljivih sistemih, sinhronizaciji niti, razporejanju niti s čakanjem / obveščanjem in smrti niti.
- Sodobno rezanje navojev: uvaja primer za sočasnost Java
java.util.concurrent
in odgovarja na pogosta vprašanja za razvijalce, ki so novi v sočasnosti Java. - Sodobni navoj za ne povsem začetnike ponuja naprednejše nasvete in najboljše prakse za delo z njimi
java.util.concurrent
.
Več od Rafaela
- Pridobite več hitrih nasvetov za kodo: preberite vse objave v seriji Java Challengers.
- Izboljšajte svoje znanje Java: Obiščite Java Dev Gym za vadbo kode.
- Bi radi delali na projektih brez stresa in pisali kodo brez napak? Obiščite NoBugsProject za svojo kopijo Brez napak, brez stresa - ustvarite programsko opremo, ki spreminja življenje, ne da bi uničili svoje življenje.
To zgodbo "Obnašanje niti v JVM" je prvotno objavil JavaWorld.