Programavimas

Įvadas į „Java“ gijas

Šiame viename iš pirmųjų „JavaWorld“ išleistame straipsnyje aprašoma, kaip gijos diegiamos „Java“ programavimo kalba, pradedant bendra gijų apžvalga.

Paprasčiau tariant, a siūlas yra programos vykdymo kelias. Dauguma šiandien parašytų programų veikia kaip viena gija, todėl kyla problemų, kai vienu metu turi įvykti keli įvykiai ar veiksmai. Tarkime, pavyzdžiui, programa nesugeba piešti paveikslėlių skaitydama klavišų paspaudimus. Programa turi skirti visą dėmesį klaviatūros įvedimui, neturinčiam galimybės valdyti daugiau nei vieno įvykio vienu metu. Idealus šios problemos sprendimas yra vientisas dviejų ar daugiau programos skyrių vykdymas vienu metu. Siūlai leidžia mums tai padaryti.

Sužinokite apie „Java“ gijas

Šis straipsnis yra „JavaWorld“ techninio turinio archyvo dalis. Norėdami sužinoti daugiau apie „Java“ gijas ir lygiagretumą, žr.

Suprasti „Java“ gijas („Java 101“ serija, 2002):

  • 1 dalis. Pristatome siūlus ir bėgimus
  • 2 dalis. Siūlų sinchronizavimas
  • 3 dalis: Gijų planavimas ir laukimas / pranešimas
  • 4 dalis. Siūlų grupės ir nepastovumas

Susiję straipsniai

  • „Hyper-threaded Java“: „Java Concurrency“ API naudojimas (2006)
  • Geresni kelių gijų programų monitoriai (2007 m.)
  • Aktoriaus sutapimo supratimas, 1 dalis (2009)
  • Pakabinamų siūlų aptikimas ir tvarkymas (2011)

Taip pat patikrinkite „JavaWorld“ svetainės žemėlapis ir paieškos variklis.

Daugelio gijų programos suteikia savo stiprią galią, vienu metu paleidžiant daugybę gijų. Loginiu požiūriu, daugialypis sriegimas reiškia, kad vienu metu gali būti vykdomos kelios vienos programos eilutės, tačiau tai nėra tas pats, kas paleisti programą du kartus ir sakyti, kad yra kelios programos eilutės, vykdomos tuo pačiu metu laikas. Šiuo atveju operacinė sistema programas vertina kaip du atskirus ir skirtingus procesus. „Unix“ sistemoje išsišakojus procesas sukuria antrinį procesą su skirtinga adreso erdve tiek kodui, tiek duomenims. Tačiau šakutė () sukuria daug pridėtinių išlaidų operacinei sistemai, todėl tai labai daug procesorių reikalaujanti operacija. Vietoj to, paleidus giją, sukuriamas efektyvus vykdymo kelias, tuo pat metu dalijantis pradinių duomenų sritimi iš tėvų. Idėja dalytis duomenų sritimi yra labai naudinga, tačiau iškelia kai kurias problemas, kurias aptarsime vėliau.

Temų kūrimas

„Java“ kūrėjai maloniai sukūrė du gijų kūrimo būdus: sąsajos diegimą ir klasės išplėtimą. Klasės išplėtimas yra tai, kaip „Java“ paveldi metodus ir kintamuosius iš tėvų klasės. Tokiu atveju pratęsti ar paveldėti galima tik iš vieno iš tėvų klasės. Šį „Java“ apribojimą galima įveikti diegiant sąsajas, o tai yra labiausiai paplitęs būdas sukurti gijas. (Atkreipkite dėmesį, kad paveldėjimo veiksmas leidžia tik paleisti klasę kaip giją. Tai priklauso nuo klasės pradžia () vykdymas ir kt.)

Sąsajos suteikia galimybę programuotojams padėti klasės pagrindus. Jie naudojami kuriant klasių rinkinio reikalavimus, kuriuos reikia įgyvendinti. Sąsaja viską nustato, o sąsają įgyvendinanti klasė ar klasės atlieka visą darbą. Skirtingi sąsają įgyvendinantys klasių rinkiniai turi laikytis tų pačių taisyklių.

Yra keletas skirtumų tarp klasės ir sąsajos. Pirma, sąsajoje gali būti tik abstraktūs metodai ir (arba) statiniai galutiniai kintamieji (konstantos). Kita vertus, klasės gali įgyvendinti metodus ir turėti kintamuosius, kurie nėra konstantos. Antra, sąsaja negali įgyvendinti jokių metodų. Sąsają diegianti klasė turi įgyvendinti visus toje sąsajoje apibrėžtus metodus. Sąsaja turi galimybę išplėsti iš kitų sąsajų ir (skirtingai nei klasės) gali išplėsti iš kelių sąsajų. Be to, sąsaja negali būti sukurta su naujuoju operatoriumi; pavyzdžiui, Vykdomas a = naujas Vykdomas (); tai yra neleistina.

Pirmasis gijų kūrimo būdas yra tiesiog pratęsti nuo Siūlas klasė. Atlikite tai tik tuo atveju, jei klasės, kurios jums reikia kaip gijos, niekada nereikia pratęsti iš kitos klasės. Siūlas klasė yra apibrėžta pakete java.lang, kurį reikia importuoti, kad mūsų klasės žinotų jo apibrėžimą.

importuoti java.lang. *; viešosios klasės skaitiklis pratęsia giją {public void run () {....}}

Aukščiau pateiktas pavyzdys sukuria naują klasę Skaitliukas kad pratęsia Siūlas klasę ir nepaiso Thread.run () metodas savo įgyvendinimui. paleisti () metodas yra tai, kai visas darbas Skaitliukas klasės siūlai yra padaryti. Tą pačią klasę galima sukurti įdiegus „Runnable“:

importuoti java.lang. *; public class Counter padargai Runnable {Thread T; public void run () {....}}

Čia abstraktus paleisti () metodas yra apibrėžtas „Runnable“ sąsajoje ir yra įgyvendinamas. Atkreipkite dėmesį, kad turime Siūlas klasė kaip kintamasis Skaitliukas klasė. Vienintelis skirtumas tarp šių dviejų metodų yra tas, kad įdiegus „Runnable“, kuriant klasę yra daugiau lankstumo Skaitliukas. Ankstesniame pavyzdyje vis dar yra galimybė išplėsti Skaitliukas klasės, jei reikia. Dauguma sukurtų klasių, kurias reikia paleisti kaip giją, įdiegs „Runnable“, nes tikriausiai jos praplečia kitas funkcijas iš kitos klasės.

Nemanykite, kad vykdoma gija sąsaja „Runnable“ atlieka tikrą darbą. Tai tik klasė, sukurta idėjai apie filmo dizainą Siūlas klasė. Iš tikrųjų jis yra labai mažas, jame yra tik vienas abstraktus metodas. Čia yra „Runnable“ sąsajos apibrėžimas tiesiai iš „Java“ šaltinio:

paketas java.lang; viešoji sąsaja Paleidžiama {public abstract void run (); }

Tai viskas, kas yra „Runnable“ sąsajoje. Sąsaja pateikia tik projektą, pagal kurį klasės turėtų būti įgyvendintos. „Runnable“ sąsajos atveju jis priverčia apibrėžti tik paleisti () metodas. Todėl didžioji dalis darbo atliekama Siūlas klasė. Atidžiau pažvelkite į apibrėžimo skyrių Siūlas klasė suteiks idėją, kas iš tikrųjų vyksta:

public class Thread realizuoja Runnable {... public void run () {if (target! = null) {target.run (); }} ...}

Iš minėto kodo fragmento akivaizdu, kad „Thread“ klasė taip pat įdiegia „Runnable“ sąsają. Siūlas.paleisti () patikrina, ar tikslinė klasė (klasė, kuri bus vykdoma kaip gija) nėra lygi nuliui, ir tada vykdo paleisti () taikinio metodas. Kai tai atsitiks, paleisti () taikinio metodas bus vykdomas kaip savo gija.

Užvedimas ir sustabdymas

Kadangi dabar yra aiškūs skirtingi gijos egzemplioriaus sukūrimo būdai, aptarsime gijų įgyvendinimą, pradedant nuo būdų, kaip juos paleisti ir sustabdyti, naudodami mažą programėlę, kurioje yra gija, kad iliustruotų mechaniką:

„CounterThread“ pavyzdys ir šaltinio kodas

Aukščiau esanti programėlė pradės skaičiuoti nuo 0, rodydama savo išvestį tiek ekrane, tiek konsolėje. Greitai peržvelgus gali susidaryti įspūdis, kad programa pradės skaičiuoti ir rodys kiekvieną skaičių, tačiau taip nėra. Atidžiau išnagrinėjus šios programėlės vykdymą, paaiškės jos tikroji tapatybė.

Šiuo atveju „CounterThread“ klasė buvo priversta įdiegti „Runnable“, nes ji pratęsė „Applet“ klasę. Kaip ir visose programėlėse, inicijuoti () metodas pirmiausia vykdomas. Į inicijuoti (), kintamasis Count pradedamas į nulį ir naujas Siūlas kuriama klasė. Praeidamas tai į Siūlas konstruktorius, naujoji gija žinos, kurį objektą paleisti. Tokiu atveju tai yra nuoroda į „CounterThread“. Sukūrus giją, ją reikia pradėti. Kvietimas pradžia () paskambins taikiniams paleisti () metodas, kuris yra „CounterThread“.paleisti (). Kvietimas pradžia () iškart grįš ir gija bus pradėta vykdyti tuo pačiu metu. Atkreipkite dėmesį, kad paleisti () metodas yra begalinis ciklas. Jis yra begalinis, nes kartą paleisti () metodas išeina, gija nustoja vykdyti. paleisti () metodas padidins kintamąjį Count, pristabdys 10 milisekundžių ir išsiųs užklausą atnaujinti programėlės ekraną.

Atkreipkite dėmesį, kad svarbu miegoti kur nors sriegyje. Jei ne, gija sunaudos visą procesoriaus laiką procesui ir neleis vykdyti jokių kitų metodų, tokių kaip gijos. Kitas būdas nutraukti gijos vykdymą yra paskambinti sustabdyti() metodas. Šiame pavyzdyje gija sustoja, kai pele paspaudžiama, kai žymeklis yra programėlėje. Priklausomai nuo kompiuterio, kuriame veikia programėlė, greičio, ne kiekvienas skaičius bus rodomas, nes didinimas atliekamas nepriklausomai nuo programėlės dažymo. Programėlės negalima atnaujinti pagal kiekvieną užklausą, todėl OS pateiks užklausas eilėje, o paskesnės atnaujinimo užklausos bus patenkintos vienu atnaujinimu. Kol atnaujinimai yra eilėje, grafas vis dar didinamas, bet nerodomas.

Sustabdoma ir atnaujinama

Sustabdžius giją, jos negalima paleisti iš naujo pradžia () komandą, nes sustabdyti() nutrauks gijos vykdymą. Vietoj to galite pristabdyti gijos vykdymą miegoti () metodas. Siūlas miegos tam tikrą laiką ir tada pradės vykdyti, kai bus pasiektas laiko limitas. Bet tai nėra idealu, jei giją reikia pradėti, kai įvyksta tam tikras įvykis. Šiuo atveju sustabdyti () metodas leidžia gijai laikinai nutraukti vykdymą ir tęsti() metodas leidžia pakabintą siūlą pradėti iš naujo. Šioje programėlėje parodytas aukščiau pateiktas pavyzdys, modifikuotas sustabdyti ir atnaujinti programėlę.

viešoji klasė „CounterThread2“ praplečia programėlių padargus „Runnable“ {Thread t; int grafas; loginė pakaba; viešoji loginė pelėDown (įvykis e, int x, int y) {if (sustabdytas) t.resume (); dar t.suspend (); sustabdytas =! sustabdytas; grįžti tiesa; } ...}

„CounterThread2“ pavyzdys ir šaltinio kodas

Norėdami sekti dabartinę programėlės būseną, loginį kintamąjį sustabdytas yra naudojamas. Skirtingas programėlės būsenas atskirti svarbu, nes kai kurie metodai išmeta išimtis, jei jos bus iškviestos esant netinkamai. Pvz., Jei programėlė buvo paleista ir sustabdyta, vykdykite pradžia () metodas meta „IllegalThreadStateException“ išimtis.