Programmēšana

Ievads Java pavedienos

Šajā rakstā, kas ir viens no pirmajiem, ko jebkad ir publicējis JavaWorld, aprakstīts, kā pavedieni tiek ieviesti Java programmēšanas valodā, sākot ar vispārīgu pavedienu pārskatu.

Vienkārši sakot, a pavediens ir programmas izpildes ceļš. Lielākā daļa šodien rakstīto programmu darbojas kā viens pavediens, radot problēmas, ja vienlaikus jānotiek vairākiem notikumiem vai darbībām. Pieņemsim, ka, piemēram, programma nespēj zīmēt attēlus, lasot taustiņsitienus. Programmai ir pilnībā jāpievērš uzmanība tastatūras ievadei, kurai trūkst iespēju vienlaikus apstrādāt vairāk nekā vienu notikumu. Ideāls šīs problēmas risinājums ir nevainojama divu vai vairāku programmas sadaļu vienlaicīga izpilde. Threads ļauj mums to izdarīt.

Uzzināt par Java pavedieniem

Šis raksts ir daļa no JavaWorld tehniskā satura arhīva. Skatiet šo, lai uzzinātu vairāk par Java pavedieniem un vienlaicīgumu:

Izpratne par Java pavedieniem (Java 101 sērija, 2002. gads):

  • 1. daļa: Vītņu un skrējienu iepazīstināšana
  • 2. daļa: Vītnes sinhronizācija
  • 3. daļa: Vītnes plānošana un gaidīšana / paziņošana
  • 4. daļa: pavedienu grupas un nepastāvība

Saistītie raksti

  • Hyper-threaded Java: Java Concurrency API izmantošana (2006)
  • Labāki daudzlīniju programmu monitori (2007)
  • Izpratne par aktiera vienlaicīgumu, 1. daļa (2009)
  • Piekārto vītņu noteikšana un apstrāde (2011)

Pārbaudiet arī JavaWorld vietnes karte un meklētājs.

Vairāku pavedienu lietojumprogrammas nodrošina savu spēcīgo jaudu, vienlaikus vienā programmā palaižot daudz pavedienu. No loģiskā viedokļa daudzsavienojums nozīmē, ka vienlaikus var izpildīt vairākas vienas programmas rindas, tomēr tas nav tas pats, kas sākt programmu divreiz un teikt, ka tajā pašā laikā tiek izpildītas vairākas programmas rindas laiks. Šajā gadījumā operētājsistēma apstrādā programmas kā divus atsevišķus un atšķirīgus procesus. Sadaļā Unix procesa dakša izveido bērnu procesu ar atšķirīgu adreses vietu gan kodam, gan datiem. Tomēr dakša () rada daudz papildu izmaksu operētājsistēmai, padarot to par ļoti CPU ietilpīgu darbību. Sākot pavedienu, tiek izveidots efektīvs izpildes ceļš, vienlaikus koplietojot sākotnējā datu apgabalu no vecākiem. Ideja par datu apgabala koplietošanu ir ļoti izdevīga, taču rada dažas bažas, kuras mēs apspriedīsim vēlāk.

Vītņu veidošana

Java veidotāji ir laipni izstrādājuši divus pavedienu veidošanas veidus: saskarnes ieviešanu un klases paplašināšanu. Klases paplašināšana ir veids, kā Java pārmanto metodes un mainīgos no vecāku klases. Šajā gadījumā var pagarināt vai mantot tikai no viena vecāka klases. Šo Java ierobežojumu var pārvarēt, ieviešot saskarnes, kas ir visizplatītākais pavedienu izveides veids. (Ņemiet vērā, ka mantošanas akts ļauj tikai klasi palaist kā pavedienu. Tas ir klases ziņā sākt() izpilde utt.)

Saskarnes nodrošina programmētājiem iespēju ielikt klases pamatu. Tos izmanto, lai izstrādātu prasības klašu kopai, kas jāīsteno. Interfeiss visu nosaka, un klase vai klases, kas ievieš saskarni, veic visu darbu. Dažādām klašu kopām, kas ievieš saskarni, ir jāievēro vieni un tie paši noteikumi.

Starp klasi un interfeisu ir dažas atšķirības. Pirmkārt, saskarne var saturēt tikai abstraktas metodes un / vai statiskus galīgos mainīgos (konstantes). Savukārt klases var ieviest metodes un satur mainīgos, kas nav konstanti. Otrkārt, interfeiss nevar ieviest nekādas metodes. Klasei, kas ievieš saskarni, jāievieš visas šajā saskarnē noteiktās metodes. Saskarnei ir iespēja paplašināties no citām saskarnēm, un (atšķirībā no klasēm) tā var paplašināties no vairākām saskarnēm. Turklāt saskarni nevar izveidot ar jauno operatoru; piemēram, Runnable a = jauns Runnable (); nav atļauts.

Pirmā pavediena izveides metode ir vienkārši pagarināt no Vītne klasē. Dariet to tikai tad, ja klase, kas jums jāizpilda kā pavediens, nekad nav jāpaplašina no citas klases. The Vītne klase ir definēta paketā java.lang, kas jāimportē, lai mūsu klases būtu informētas par tās definīciju.

importēt java.lang. *; public class Counter paplašina Thread {public void run () {....}}

Iepriekš minētais piemērs rada jaunu klasi Skaitītājs kas paplašina Vītne klasi un ignorē Thread.run () metode tās īstenošanai. The palaist () metode ir tā, kur viss Skaitītājs klases pavediens ir izdarīts. To pašu klasi var izveidot, ieviešot Runnable:

importēt java.lang. *; publiskās klases skaitītāja rīki Runnable {Thread T; public void run () {....}}

Lūk, abstrakts palaist () metode ir definēta Runnable saskarnē un tiek ieviesta. Ņemiet vērā, ka mums ir Vītne klase kā mainīgais Skaitītājs klasē. Vienīgā atšķirība starp abām metodēm ir tā, ka, ieviešot Runnable, klases izveidē ir lielāka elastība Skaitītājs. Iepriekš minētajā piemērā joprojām pastāv iespēja paplašināt Skaitītājs klase, ja nepieciešams. Lielākā daļa izveidoto klašu, kuras jāpalaiž kā pavedieni, ieviesīs Runnable, jo tās, iespējams, paplašina citas funkcijas no citas klases.

Nedomājiet, ka Runnable saskarne veic reālu darbu, kad pavediens tiek izpildīts. Tā ir tikai klase, kas izveidota, lai dotu priekšstatu par Vītne klasē. Faktiski tas ir ļoti mazs un satur tikai vienu abstraktu metodi. Šeit ir Runnable saskarnes definīcija tieši no Java avota:

pakete java.lang; publiskā saskarne Runnable {public abstract void run (); }

Tas ir viss, kas ir Runnable saskarnē. Saskarne nodrošina tikai dizainu, pēc kura klases jāievieš. Runnable saskarnes gadījumā tas liek definēt tikai palaist () metodi. Tāpēc lielākā daļa darba tiek veikta Vītne klasē. Sīkāk apskatīt sadaļu definīcijā Vītne klase sniegs priekšstatu par to, kas patiesībā notiek:

public class Vītne realizē Runnable {... public void run () {if (target! = null) {target.run (); }} ...}

No iepriekš minētā koda fragmenta ir skaidrs, ka Thread klase ievieš arī Runnable saskarni. Vītne.palaist () pārbauda, ​​vai mērķa klase (klase, kas tiks palaista kā pavediens) nav vienāda ar nulli, un pēc tam izpilda palaist () mērķa metode. Kad tas notiek, palaist () mērķa metode darbosies kā savs pavediens.

Sākšana un apstāšanās

Tā kā tagad ir redzami dažādi pavedienu instances izveidošanas veidi, mēs apspriedīsim pavedienu ieviešanu, sākot ar pieejamajiem veidiem, kā tos sākt un apturēt, izmantojot nelielu sīklietotni, kurā ir pavediens, lai ilustrētu mehāniku:

CounterThread piemērs un pirmkods

Iepriekš minētā sīklietotne sāks skaitīt no 0, parādot tā izvadi gan uz ekrāna, gan konsoles. Veicot ātru skatienu, varētu rasties iespaids, ka programma sāks skaitīt un parādīt katru skaitli, taču tas tā nav. Rūpīgāk pārbaudot šīs sīklietotnes izpildi, tiks atklāta tā patiesā identitāte.

Šajā gadījumā CounterThread klase bija spiesta ieviest Runnable, jo tā paplašināja klase Applet. Tāpat kā visās sīklietotnēs, arī tajā() metode tiek izpildīta vispirms. In tajā(), mainīgais Count tiek inicializēts uz nulli un tiek parādīts jauns Vītne klase ir izveidota. Garāmejot šo uz Vītne konstruktors, jaunais pavediens zinās, kuru objektu palaist. Šajā gadījumā šo ir atsauce uz CounterThread. Pēc pavediena izveides tas ir jāsāk. Zvans uz sākt() piezvanīs mērķa palaist () metodi, kas ir CounterThread.palaist (). Zvans uz sākt() uzreiz atgriezīsies, un pavediens sāks izpildīt vienlaikus. Ņemiet vērā, ka palaist () metode ir bezgalīga cilpa. Tas ir bezgalīgs, jo reiz palaist () metode iziet, pavediens pārtrauc izpildi. The palaist () metode palielinās mainīgo Count, gulēs 10 milisekundes un nosūtīs pieprasījumu atsvaidzināt sīklietotnes displeju.

Ņemiet vērā, ka ir svarīgi gulēt kaut kur pavedienā. Ja nē, pavediens patērēs visu procesora laiku procesam un neļaus izpildīt citas metodes, piemēram, pavedienus. Vēl viens veids, kā pārtraukt pavediena izpildi, ir izsaukt apstāties () metodi. Šajā piemērā pavediens apstājas, nospiežot peli, kamēr kursors atrodas sīklietotnē. Atkarībā no datora ātruma, kurā darbojas sīklietotne, visi skaitļi netiks parādīti, jo pieaugums tiek veikts neatkarīgi no sīklietotnes krāsošanas. Sīklietotni nevar atsvaidzināt pēc katra pieprasījuma, tāpēc OS rindos pieprasījumus un secīgie atsvaidzināšanas pieprasījumi tiks apmierināti ar vienu atsvaidzināšanu. Kamēr atsvaidzinājumi ir rindā, Count joprojām tiek palielināts, bet netiek parādīts.

Pārtrauc un atsāk

Kad pavediens ir apturēts, to nevar atsākt ar sākt() komandu, kopš apstāties () pārtrauks pavediena izpildi. Tā vietā jūs varat apturēt pavediena izpildi ar Gulēt() metodi. Vītne gulēs noteiktu laiku un pēc tam sāks izpildīt, kad būs sasniegts laika ierobežojums. Bet tas nav ideāli, ja pavediens jāsāk, kad notiek noteikts notikums. Šajā gadījumā apturēt () metode ļauj pavedienam uz laiku pārtraukt izpildi un turpināt() metode ļauj apturēto pavedienu sākt no jauna. Šajā sīklietotnē parādīts iepriekš minētais piemērs, kas pārveidots, lai apturētu un atsāktu sīklietotni.

publiskā klase CounterThread2 paplašina sīklietotnes rīkus Runnable {Thread t; int Count; Boolean apturēts; publiskā būla peleDown (notikums e, int x, int y) {if (apturēts) t.resume (); cits t.suspend (); apturēts =! apturēts; atgriezties taisnība; } ...}

CounterThread2 piemērs un pirmkods

Lai sekotu sīklietotnes pašreizējam stāvoklim, Būla mainīgais apturēts tiek izmantots. Ir svarīgi atšķirt sīklietotnes dažādos stāvokļus, jo dažas metodes radīs izņēmumus, ja tos izsauks, atrodoties nepareizā stāvoklī. Piemēram, ja sīklietotne ir palaista un apturēta, izpildot sākt() metode iemetīs IllegalThreadStateException izņēmums.

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