Programavimas

Šiuolaikinis sriegimas: „Java“ lygiagretumo pradas

Daugybė dalykų, kuriuos reikia sužinoti apie programavimą naudojant „Java“ gijas, per „Java“ platformos raidą smarkiai nepasikeitė, tačiau pakito palaipsniui. Šiame „Java“ gijų pradiniame eteryje Cameronas Lairdas pataiko į kai kuriuos aukštus (ir žemus) siūlų taškus kaip tuo pačiu programavimo būdą. Gaukite apžvalgą apie tai, kas daugelį metų kelia iššūkius daugialypiam programavimui ir sužinokite, kaip „Java“ platforma vystėsi, kad atitiktų kai kuriuos iššūkius.

Vienalaikiškumas kelia daugiausiai rūpesčių naujiems „Java“ programavimo naujokams, tačiau nėra jokios priežasties leisti tai gąsdinti. Yra ne tik puiki dokumentacija (šiame straipsnyje panagrinėsime kelis šaltinius), bet ir „Java“ temas tapo lengviau dirbti, nes „Java“ platforma vystėsi. Norint sužinoti, kaip atlikti daugialypį programavimą „Java 6“ ir „7“, jums tikrai reikia tik kai kurių statybinių elementų. Mes pradėsime nuo šių:

  • Paprasta programa su gijomis
  • Siūlai yra susiję su greičiu, tiesa?
  • „Java“ lygiagretumo iššūkiai
  • Kada naudoti „Runnable“
  • Kai blogos gijos sugenda
  • Kas naujo „Java 6“ ir „7“
  • Kas bus toliau naudojant „Java“ gijas

Šis straipsnis yra pradedančiųjų „Java“ sriegimo technikos apžvalga, įskaitant nuorodas į kai kuriuos „JavaWorld“ dažniausiai skaitomus įvadinius straipsnius apie daugiagijį programavimą. Paleiskite savo variklius ir vadovaukitės aukščiau pateiktomis nuorodomis, jei esate pasirengęs šiandien pradėti mokytis apie „Java“ diegimą.

Paprasta programa su gijomis

Apsvarstykite šį „Java“ šaltinį.

Sąrašas 1. „FirstThreadingExample“

class FirstThreadingExample {public static void main (String [] args) {// Antrasis argumentas yra vėlavimas tarp // iš eilės išvesties. Vėlavimas // matuojamas milisekundėmis. „10“, pvz., // reiškia „spausdinti eilutę kas // šimtąją sekundės dalį“. ExampleThread mt = new ExampleThread ("A", 31); „ExampleThread“ mt2 = naujas „ExampleThread“ („B“, 25); „ExampleThread“ mt3 = naujas „ExampleThread“ („C“, 10); mt.start (); mt2.start (); mt3.start (); }} klasė „ExampleThread“ pratęsia „Thread“ {private int delay; public ExampleThread (String label, int d) {// Suteikite šiai gijai // pavadinimą: "thread 'LABEL'". super ("siūlas" "+ etiketė +" ""); vėlavimas = d; } public void run () {for (int skaičius = 1, eilutė = 1; eilutė <20; eilutė ++, skaičius ++) {pabandykite {System.out.format ("#% d eilutė iš% s \ n", count, getName ()); Thread.currentThread (). Miegas (delsa); } catch (InterruptedException ie) {// Tai būtų staigmena. }}}}

Dabar sukompiliuokite ir paleiskite šį šaltinį, kaip ir bet kurią kitą „Java“ komandinės eilutės programą. Pamatysite išvestį, kuri atrodo maždaug taip:

Sąrašas 2. Srieginės programos išvestis

1 eilutė nuo sriegio „A“ 1 eilutė nuo „C“ sriegio 1 eilutė nuo sriegio „B“ 2 eilutė nuo sriegio „C“ 3 eilutė nuo „C“ srities eilutė Nr. 2 nuo „B“ srities eilutė Nr. 4 iš „C“ sriegio ... Linija Nr. 17 iš „B“ sriegio. Linija Nr. 14 iš „A“ sriegio. Linija Nr. 18 iš „B“ sriegio. Linija Nr. 18 iš „B“ sriegio. Nr. 16 iš „A“ gijos. Linija Nr. 17 iš „A“ gijos. Linija Nr. 18 iš „A“ gijos. Linija Nr. 19 iš „A“ gijos.

Viskas - tu esi „Java“ Siūlas programuotojas!

Na, gerai, gal ne taip greitai. Kad ir kokia maža yra 1 sąrašo programa, joje yra keletas subtilybių, kurios nusipelno mūsų dėmesio.

Siūlai ir neapibrėžtumas

Tipiškas mokymosi ciklas su programavimu susideda iš keturių etapų: (1) Studijuokite naują koncepciją; (2) vykdyti pavyzdinę programą; (3) palyginti produkciją su lūkesčiais; ir (4) kartoti iki dviejų rungtynių. Tačiau atkreipkite dėmesį, kad anksčiau sakiau išvestį „FirstThreadingExample“ atrodytų „kažkas panašaus“ į 2 sąrašą. Taigi, tai reiškia, kad jūsų išvestis gali skirtis nuo mano, eilutė po eilutės. Kas kad apie?

Paprasčiausiose „Java“ programose yra vykdymo užtikrinimo garantija: pirmoji eilutė pagrindinis () pirmiausia bus įvykdytas, paskui kitas ir t. t., tinkamai atsekant ir pašalinant kitus metodus. Siūlas susilpnina tą garantiją.

Siūlai suteikia naujos galios „Java“ programavimui; rezultatų galite pasiekti naudodami gijas, kurių negalėtumėte apsieiti be jų. Tačiau ta galia kainuoja ryžtas. Paprasčiausiose „Java“ programose yra vykdymo užtikrinimo garantija: pirmoji eilutė pagrindinis () bus įvykdytas pirmiausia, paskui kitas ir t. t., tinkamai atsekant ir pašalinant kitus metodus. Siūlas susilpnina tą garantiją. Daugialypėje programoje "17 eilutė nuo sriegio B„gali pasirodyti ekrane prieš arba po“14 eilutė nuo A gijos", o tvarka gali skirtis vykdant tą pačią programą, net tame pačiame kompiuteryje.

Neapibrėžtumas gali būti nepažįstamas, tačiau tai neturi kelti nerimo. Vykdymo tvarka per gija išlieka nuspėjama, taip pat yra privalumų, susijusių su neapibrėžtumu. Galbūt patyrėte kažką panašaus dirbdami su grafinėmis vartotojo sąsajomis (GUI). Pavyzdžiai yra „Swing“ įvykių klausytojai arba HTML tvarkytojai.

Nors visa įžvalga apie gijų sinchronizavimą nepatenka į šios įžangos sritį, lengva paaiškinti pagrindus.

Pavyzdžiui, apsvarstykite HTML nurodymo mechaniką ... onclick = "myFunction ();" ... nustatyti veiksmą, kuris įvyks spustelėjus vartotojui. Šis įprastas neapibrėžtumo atvejis parodo kai kuriuos jo pranašumus. Tokiu atveju, „myFunction“ () nėra vykdomas nustatytu laiku kitų šaltinio kodo elementų atžvilgiu, bet galutinio vartotojo veiksmų atžvilgiu. Taigi neapibrėžtumas nėra tik sistemos silpnybė; tai taip pat praturtėjimas vykdymo modelio, kuris suteikia programuotojui naujų galimybių nustatyti seką ir priklausomybę.

Vykdymo atidėjimai ir siūlų poklasis

Galite pasimokyti iš „FirstThreadingExample“ eksperimentuodami patys. Pabandykite pridėti arba pašalinti Gijos pavyzdyss - tai yra konstruktorių iškvietimai kaip ... naujas „ExampleThread“ (etiketė, vėlavimas); - ir tinti uždelsimass. Pagrindinė mintis yra ta, kad programa prasideda trys atskirai Siūlass, kurie tada veikia savarankiškai iki pabaigos. Kad jų vykdymas būtų pamokomesnis, kiekvienas šiek tiek vėluoja tarp eilės eilių, kurias rašo išvesdamas; tai suteikia kitoms temoms galimybę rašyti produkcija.

Prisimink tai Siūlaspagrindiniu programavimu paprastai nereikia tvarkyti Nutraukta išimtis. Parodytas „FirstThreadingExample“ susijęs su miegoti (), o ne tiesiogiai susiję su Siūlas. Dauguma Siūlas-pagrindiniame šaltinyje nėra a miegoti (); tikslas miegoti () čia reikia paprastu būdu modeliuoti „laukinėje gamtoje“ aptinkamų seniai taikomų metodų elgesį.

Kažkas dar pastebimas 1 sąraše yra tai Siūlas yra abstraktus klasė, skirta subklasėms. Numatytasis paleisti () metodas nieko nedaro, todėl norint jį pasiekti, kad būtų naudinga, jis turi būti pakeistas poklasio apibrėžime.

Visa tai susiję su greičiu, tiesa?

Taigi dabar galite pamatyti šiek tiek to, dėl ko sudėtingas programavimas su gijomis. Tačiau svarbiausia iškęsti visus šiuos sunkumus nėra įgyti greitį.

Daugiagrybės programos nereikia, apskritai, užbaigti greičiau nei viengijų siūlų - iš tikrųjų jie gali būti žymiai lėtesni patologiniais atvejais. Pagrindinė daugelio gijų programų pridėtinė vertė yra reagavimas. Kai JVM gali naudotis keliais apdorojimo šerdimis arba kai programa praleidžia daug laiko laukdama daugybės išorinių išteklių, tokių kaip tinklo atsakymai, daugialypis sriegimas gali padėti programai greičiau užbaigti.

Pagalvokite apie GUI programą: jei ji vis tiek reaguoja į galutinio vartotojo taškus ir paspaudimus ieškodama „fone“ atitinkamo piršto atspaudo arba iš naujo apskaičiuodama kitų metų teniso turnyro kalendorių, tai ji buvo sukurta turint omenyje sutapimą. Tipiška tuo pačiu metu esanti programos architektūra atpažįsta ir atsako į vartotojo veiksmus gijoje, atskiroje nuo skaičiavimo gijų, priskirtų tvarkyti didelę galinę apkrovą. (Daugiau informacijos apie šiuos principus rasite skyriuje „Sūpynės sriegimas ir įvykio siuntimo sriegis“.)

Savo programavime tada greičiausiai apsvarstysite galimybę naudoti Siūlass esant vienai iš šių aplinkybių:

  1. Esama programa turi teisingą funkciją, tačiau kartais nereaguoja. Šie „blokai“ dažnai yra susiję su išoriniais ištekliais, kurių jūs negalite valdyti: daug laiko reikalaujančios duomenų bazės užklausos, sudėtingi skaičiavimai, daugialypės terpės atkūrimas ar tinkliniai atsakymai su nekontroliuojamu vėlavimu.
  2. Intensyviai skaičiavimams taikoma programa galėtų geriau panaudoti daugiagyslius pagrindinius kompiuterius. Tai gali būti kažkas, pateikiantis sudėtingą grafiką ar imituojantis susijusį mokslinį modelį.
  3. Siūlas natūraliai išreiškia reikalingą programos programavimo modelį. Tarkime, pavyzdžiui, jūs modeliavote piko valandos automobilių vairuotojų ar bičių elgesį avilyje. Kiekvieną vairuotoją ar bitę įgyvendinti kaip a Siūlassusijęs objektas gali būti patogus programavimo požiūriu, išskyrus bet kokius greičio ar reagavimo aspektus.

„Java“ lygiagretumo iššūkiai

Neseniai kvatojo patyręs programuotojas Nedas Batchelderis

Kai kurie žmonės, susidūrę su problema, galvoja: „Aš žinau, aš naudosiu siūlus“, o paskui du jie išsiskleidžia.

Tai juokinga, nes taip gerai modeliuojama lygiagretumo problema. Kaip jau minėjau, greičiausiai daugialypės programos duos skirtingus rezultatus, kalbant apie tikslią gijų vykdymo seką ar laiką. Tai kelia nerimą programuotojams, kurie yra išmokyti mąstyti pagal atkuriamus rezultatus, griežtą ryžtą ir nekintamą seką.

Blogėja. Skirtingos gijos gali ne tik pateikti rezultatus skirtinga tvarka, bet ir gali ginčytis svarbesniais rezultatų lygiais. Naujokui lengva rinktis daugiasluoksnį ryšį Uždaryti() failo rankena viename Siūlas prieš kitokį Siūlas baigė viską, ką reikia parašyti.

Vienalaikių programų testavimas

Prieš dešimt metų „JavaWorld“ svetainėje Dave'as Dyyeris pažymėjo, kad „Java“ kalba turėjo vieną ypatybę, kuri buvo „taip dažnai naudojama neteisingai“, kad jis ją įvertino kaip rimtą dizaino trūkumą. Ta savybė buvo daugialypė.

Dyerio komentaras pabrėžia iššūkį išbandyti daugiasluoksnes programas. Kai nebegalėsite lengvai nurodyti programos išvesties pagal tam tikrą simbolių seką, tai turės įtakos tam, kaip efektyviai galite patikrinti savo srieginį kodą.

Teisingą atskaitos tašką sprendžiant būdingus tuo pačiu metu vykstančio programavimo sunkumus Heinzas Kabutzas savo „Java Specialist“ informaciniame biuletenyje gerai nurodė: pripažinkite, kad lygiagretumas yra tema, kurią turėtumėte suprasti ir sistemingai ją nagrinėti. Žinoma, kad bus naudingos tokios priemonės kaip diagramų schemos ir oficialios kalbos. Tačiau pirmas žingsnis yra sustiprinti intuiciją praktikuojant tokias paprastas programas kaip „FirstThreadingExample“ sąraše 1. Tada sužinokite kuo daugiau apie tokius pagrindų sriegius:

  • Sinchronizacija ir nekintami objektai
  • Gijos planavimas ir laukimas / pranešimas
  • Lenktynių sąlygos ir aklavietė
  • Siūlų monitoriai, skirti išskirtinei prieigai, sąlygoms ir tvirtinimams
  • Geriausia „JUnit“ praktika - daugiasluoksnio kodo testavimas

Kada naudoti „Runnable“

Objektų orientacija „Java“ apibrėžia pavieniai paveldėtas klases, o tai turi pasekmių daugelio gijų kodavimui. Iki šiol aš aprašiau tik naudojimą Siūlas kad buvo pagrįsta poklasiais su nepaisytais paleisti (). Dizaino objekte, kuris jau buvo susijęs su paveldėjimu, tai paprasčiausiai neveiks. Jūs negalite vienu metu paveldėti iš „RenderedObject“ arba Gamybos linija arba „MessageQueue“ greta Siūlas!

Šis suvaržymas daro įtaką daugeliui „Java“ sričių, ne tik daugiasluoksniam gijimui. Laimei, yra klasikinis problemos sprendimas Bėgama sąsaja. Kaip paaiškino Jeffas Friesenas 2002 m Bėgama sąsaja yra sukurta situacijoms, kai poklasis Siūlas negalima:

Bėgama sąsaja deklaruoja vieno metodo parašą: niekinis bėgimas ();. Tas parašas yra identiškas Siūlas's paleisti () metodo parašas ir tarnauja kaip gijos vykdymo įrašas. Nes Bėgama yra sąsaja, bet kuri klasė gali įdiegti tą sąsają, pridėdama padargai klasės antraštėje ir pateikiant tinkamą paleisti () metodas. Vykdymo metu programos kodas gali sukurti objektą arba bėgama, iš tos klasės ir perduodate bėgimo nuorodą į tinkamą Siūlas konstruktorius.

Taigi toms klasėms, kurios negali pratęsti Siūlas, norėdami pasinaudoti kelių sriegių teikiamais privalumais, turite sukurti paleidžiamą. Semantiškai, jei programuojate sistemos lygio ir jūsų klasė yra susijusi su Siūlas, tada turėtumėte subklasę tiesiogiai iš Siūlas. Tačiau dauguma daugialypių gijų taikymo lygio priklauso nuo kompozicijos ir taip apibrėžia a Bėgama suderinama su programos klasės diagrama. Laimei, norint koduoti reikia tik papildomos eilutės ar dviejų Bėgama sąsaja, kaip parodyta žemiau esančiame 3 sąraše.

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