Programiranje

Obnašanje niti v JVM

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 Navojje zač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.
Rafael Chinelato Del Nero

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 a System.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:

  1. Začetek izvajanja v glavni niti.
  2. Natisnite številke od 1 do 100.000.
  3. 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 Davidsonin 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_PRIORITYni 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 a Navoj.
  • 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.

$config[zx-auto] not found$config[zx-overlay] not found