The Codest
  • Apie mus
  • Paslaugos
    • Programinės įrangos kūrimas
      • Priekinės dalies kūrimas
      • Galinės dalies kūrimas
    • Staff Augmentation
      • Priekinės dalies kūrėjai
      • Atgalinės versijos kūrėjai
      • Duomenų inžinieriai
      • Debesų inžinieriai
      • QA inžinieriai
      • Kita
    • Patariamoji tarnyba
      • Auditas ir konsultacijos
  • Pramonės šakos
    • Fintech ir bankininkystė
    • E-commerce
    • Adtech
    • Sveikatos technologijos
    • Gamyba
    • Logistika
    • Automobiliai
    • IOT
  • Vertė už
    • CEO
    • CTO
    • Pristatymo vadybininkas
  • Mūsų komanda
  • Case Studies
  • Sužinokite, kaip
    • Tinklaraštis
    • Susitikimai
    • Interneto seminarai
    • Ištekliai
Karjera Susisiekite su mumis
  • Apie mus
  • Paslaugos
    • Programinės įrangos kūrimas
      • Priekinės dalies kūrimas
      • Galinės dalies kūrimas
    • Staff Augmentation
      • Priekinės dalies kūrėjai
      • Atgalinės versijos kūrėjai
      • Duomenų inžinieriai
      • Debesų inžinieriai
      • QA inžinieriai
      • Kita
    • Patariamoji tarnyba
      • Auditas ir konsultacijos
  • Vertė už
    • CEO
    • CTO
    • Pristatymo vadybininkas
  • Mūsų komanda
  • Case Studies
  • Sužinokite, kaip
    • Tinklaraštis
    • Susitikimai
    • Interneto seminarai
    • Ištekliai
Karjera Susisiekite su mumis
Atgal rodyklė GRĮŽTI ATGAL
2022-06-15
Programinės įrangos kūrimas

"Java" greitaveika. 1 dalis - įvadas

The Codest

Rafal Sawicki

"Java" programuotojas

Perskaitykite pirmąją mūsų tinklaraščio serijos, skirtos "Java" lygiagretinimui, dalį. Šiame straipsnyje plačiau apžvelgsime skirtumus tarp gijų ir procesų, gijų baseinus, vykdytojus ir dar daugiau!

Apskritai įprastinis programavimo metodas yra nuoseklus. Programoje viskas vyksta po vieną žingsnį.
Tačiau iš tiesų lygiagrečiai veikia visas pasaulis - tai gebėjimas vienu metu atlikti daugiau nei vieną užduotį.

Sriegis ir procesas

Aptarti tokias pažangias temas kaip lygiagretumas Java arba daugiajutiklį, turime susitarti dėl bendrų apibrėžčių, kad būtume tikri, jog sutinkame tą patį.

Pradėkime nuo pagrindinių dalykų. Nenuosekliajame pasaulyje turime dviejų rūšių lygiagretumo atstovus: procesus ir
siūlai. Procesas yra vykdomos programos egzempliorius. Paprastai jis yra izoliuotas nuo kitų procesų.
Operacinė sistema yra atsakinga už išteklių priskyrimą kiekvienam procesui. Be to, ji veikia kaip laidininkas, kuris
sudaro tvarkaraščius ir juos kontroliuoja.

Siūlai yra tam tikros rūšies procesas, tačiau žemesnio lygio, todėl jie dar vadinami lengvaisiais siūlais. Vienoje sistemoje gali veikti kelios gijos
procesas. Čia programa veikia kaip tvarkaraščio sudarytojas ir gijų valdiklis. Taip atskiros programos atrodo atliekančios
vienu metu atlikti kelias užduotis.

Esminis skirtumas tarp gijų ir procesų yra izoliacijos lygis. Procesas turi savo rinkinį
išteklių, o gija dalijasi duomenys su kitomis gijomis. Gali atrodyti, kad tai yra klaidingas metodas, ir iš tiesų taip yra. Dėl
dabar neskirkime tam dėmesio, nes tai išeina už šio straipsnio ribų.

Procesai, gijos - gerai... Bet kas yra lygiagretumas? Sklandumas reiškia, kad vienu metu galite vykdyti kelias užduotis.
laikas. Tai nereiškia, kad tos užduotys turi būti atliekamos vienu metu - būtent tai ir yra lygiagretumas. Concurrenc in Javay taip pat neturi
reikia kelių procesorių ar net kelių branduolių. Tai galima pasiekti vieno branduolio aplinkoje naudojant
konteksto perjungimas.

Su lygiagretumu susijęs terminas yra daugiaprocesoriškumas. Tai programų savybė, leidžianti joms vienu metu vykdyti kelias užduotis. Ne kiekviena programa taiko šį metodą, tačiau tos, kurios tai daro, gali būti vadinamos daugiagrandinėmis.

Esame beveik pasiruošę, tik dar vienas apibrėžimas. Asinchronizacija reiškia, kad programa atlieka neblokines operacijas.
Jis inicijuoja užduotį ir laukdamas atsakymo atlieka kitus veiksmus. Gavęs atsakymą, jis gali reaguoti į jį.

Visas šis džiazas

Pagal numatytuosius nustatymus kiekvienas "Java" programa paleidžiamas vienu procesu. Tame procese yra viena gija, susijusi su pagrindinis() metodas
paraišką. Tačiau, kaip minėta, galima pasinaudoti kelių gijų mechanizmais vienoje
programa.

Vykdomas

Sriegis yra Java klasė, kurioje įvyksta stebuklas. Tai yra anksčiau minėtos gijos objekto atvaizdavimas. Į
sukurti savo giją, galite išplėsti Sriegis klasė. Tačiau tai nerekomenduojama. Siūlai turėtų būti naudojamas kaip užduoties vykdymo mechanizmas. Užduotys yra dalys kodas kurį norime paleisti lygiagrečiuoju režimu. Juos galime apibrėžti naudodami Vykdomas sąsaja.

Bet užteks teorijos, dėliokime kodą ten, kur yra mūsų burna.

Problema

Tarkime, kad turime keletą skaičių masyvų. Norime sužinoti kiekvieno masyvo skaičių sumą. Tegul
apsimesti, kad tokių masyvų yra daug ir kiekvienas iš jų yra gana didelis. Esant tokioms sąlygoms, norime pasinaudoti vienalaikiškumu ir kiekvieną masyvą sumuoti kaip atskirą užduotį.

int[] a1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] a2 = {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10};
int[] a3 = {3, 4, 3, 4, 4, 3, 4, 2, 1, 3, 7};

Runnable task1 = () -> {
    int sum = Arrays.stream(a1).sum();
    System.out.println("1. Suma yra: " + suma);
};

Runnable task2 = () -> {
    int sum = Arrays.stream(a2).sum();
    System.out.println("2. Suma yra: " + suma);
};

Runnable task3 = () -> {
    int sum = Arrays.stream(a3).sum();
    System.out.println("3. Suma yra: " + suma);
};

new Thread(task1).start();
new Thread(task2).start();
new Thread(task3).start();

Kaip matote iš pirmiau pateikto kodo Vykdomas yra funkcinė sąsaja. Joje yra vienas abstraktus metodas paleisti()
be jokių argumentų. Adresas Vykdomas sąsaja turėtų būti įgyvendinta bet kurioje klasėje, kurios egzemplioriai turi būti
vykdoma gija.

Apibrėžę užduotį, galite sukurti giją jai vykdyti. Tai galima padaryti naudojant nauja gija() konstruktorius, kuris
užima Vykdomas kaip argumentas.

Paskutinis žingsnis - paleisti() naujai sukurta gija. API taip pat yra paleisti() metodai Vykdomas ir
Sriegis. Tačiau tai nėra būdas išnaudoti "Java" lygiagretumą. Tiesioginis kiekvieno iš šių metodų iškvietimas sukelia
užduoties vykdymas tame pačiame sraute. pagrindinis() paleidžiamas metodas.

Srautų telkiniai ir vykdytojai

Kai užduočių yra daug, kurti atskirą giją kiekvienai užduočiai nėra gera idėja. Sukurti Sriegis yra
sunkią operaciją, todėl daug geriau pakartotinai naudoti esamas gijas nei kurti naujas.

Kai programa sukuria daug trumpalaikių gijų, geriau naudoti gijų fondą. Srautų fondą sudaro kelios
paruoštas paleisti, bet šiuo metu neaktyvias gijas. Suteikiant a Vykdomas į fondą, vienas iš srautų iškviečia
paleisti() pateiktas metodas Vykdomas. Atlikus užduotį, gija vis dar egzistuoja ir yra neveikos būsenoje.

Gerai, supratote - pageidaujate siūlų fondo, o ne rankinio kūrimo. Bet kaip galite pasinaudoti siūlų baseinais? Svetainė Vykdytojai
klasė turi keletą statinių gamyklinių metodų, skirtų siūlų fondams kurti. Pavyzdžiui newCachedThredPool() sukuria
fondą, kuriame naujos gijos kuriamos pagal poreikį, o nenaudojamos gijos saugomos 60 sekundžių. Priešingai,
newFixedThreadPool() yra fiksuotas gijų rinkinys, kuriame neveikiančios gijos laikomos neribotą laiką.

Pažiūrėkime, kaip tai galėtų veikti mūsų pavyzdyje. Dabar mums nebereikia kurti gijų rankiniu būdu. Vietoj to turime sukurti
ExecutorService kuri suteikia gijų fondą. Tada galime priskirti jam užduotis. Paskutinis žingsnis - uždaryti giją
fondą, kad būtų išvengta atminties nutekėjimo. Likusi ankstesnio kodo dalis išlieka tokia pati.

ExecutorService executor = Executors.newCachedThreadPool();

executor.submit(task1);
executor.submit(task2);
executor.submit(task3);

executor.shutdown();

Skambinamas

Vykdomas atrodo puikus būdas kurti lygiagrečias užduotis, tačiau jis turi vieną didelį trūkumą. Jis negali grąžinti jokių
vertė. Be to, negalime nustatyti, ar užduotis baigta, ar ne. Taip pat nežinome, ar ji buvo baigta
paprastai arba išimties tvarka. Šių ligų sprendimas yra Skambinamas.

Skambinamas yra panašus į Vykdomas taip pat apima asinchronines užduotis. Pagrindinis skirtumas yra tas, kad jis gali
grąžinti reikšmę. Grąžinama vertė gali būti bet kokio (ne primityvaus) tipo, nes Skambinamas sąsaja yra parametrizuotas tipas.
Skambinamas yra funkcinė sąsaja, turinti skambinti() metodą, kuris gali išmesti Išimtis.

Dabar pažiūrėkime, kaip galime panaudoti Skambinamas mūsų masyvo uždavinyje.

int[] a1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] a2 = {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10};
int[] a3 = {3, 4, 3, 4, 4, 3, 4, 2, 1, 3, 7};

Callable task1 = () -> Arrays.stream(a1).sum();
Callable task2 = () -> Arrays.stream(a2).sum();
Callable task3 = () -> Arrays.stream(a3).sum();

ExecutorService executor = Executors.newCachedThreadPool();
Future future1 = executor.submit(task1);
Future future2 = executor.submit(task2);
Future future3 = executor.submit(task3);

System.out.println("1. Suma yra: " + future1.get());
System.out.println("2. Suma yra: " + future2.get());
System.out.println("3. Suma yra: " + future3.get());

executor.shutdown();

Gerai, matome, kaip Skambinamas sukuriamas ir pateikiamas ExecutorService. Bet kas, po velnių, yra Ateitis?
Ateitis veikia kaip tiltas tarp gijų. Kiekvieno masyvo suma sukuriama atskiroje gijoje, todėl mums reikia būdo, kaip
gauti šiuos rezultatus atgal į pagrindinis().

Norėdami gauti rezultatą iš Ateitis turime skambinti gauti() metodas. Čia gali nutikti vienas iš dviejų dalykų. Pirma,
skaičiavimo, atlikto Skambinamas yra. Tuomet ją gauname iš karto. Antra, rezultatas nėra
dar nepasiruošę. Tokiu atveju gauti() metodas bus užblokuotas, kol bus gautas rezultatas.

ComputableFuture

Problema su Ateitis yra tai, kad jis veikia pagal "stūmimo paradigmą". Naudojant Ateitis turite būti kaip bosas, kuris
nuolat klausia: "Ar tavo užduotis atlikta? Ar ji paruošta?", kol bus pasiektas rezultatas. Veikti veikiant nuolatiniam spaudimui yra
brangiai kainuoja. Geriau būtų užsisakyti Ateitis ką daryti, kai jis bus pasirengęs atlikti užduotį. Deja,
Ateitis negali to padaryti, bet ComputableFuture gali.

ComputableFuture veikia pagal "traukimo paradigmą". Galime nurodyti, ką daryti su rezultatu, kai jis atliks savo užduotis. Jis
yra asinchroninio metodo pavyzdys.

ComputableFuture puikiai veikia su Vykdomas bet ne su Skambinamas. Vietoj to galima pateikti užduotį
ComputableFuture forma Tiekėjas.

Pažiūrėkime, kaip tai susiję su mūsų problema.

int[] a1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] a2 = {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10};
int[] a3 = {3, 4, 3, 4, 4, 3, 4, 2, 1, 3, 7};

CompletableFuture.supplyAsync(() -> Arrays.stream(a1).sum())
                .thenAccept(System.out::println);

CompletableFuture.supplyAsync(() -> Arrays.stream(a2).sum())
                .thenAccept(System.out::println);

CompletableFuture.supplyAsync(() -> Arrays.stream(a3).sum())
                .thenAccept(System.out::println);

Pirmiausia į akis krenta tai, kad šis sprendimas yra daug trumpesnis. Be to, jis taip pat atrodo švarus ir tvarkingas.

Užduotis UžbaigiamaBūsimybė gali teikti supplyAsync() metodą, kuris priima Tiekėjas arba runAsync() kad
užima Vykdomas. Grįžtamasis ryšys - kodo dalis, kuri turėtų būti paleista užbaigus užduotį - apibrėžiamas thenAccept()
metodas.

Išvados

Java pateikiama daug skirtingų požiūrių į lygiagretumą. Šiame straipsnyje vos palietėme šią temą.

Nepaisant to, apžvelgėme pagrindinius Sriegis, Vykdomas, Skambinamas, ir CallableFuture kuris kelia gerą klausimą
tolesniam temos tyrimui.

Susiję straipsniai

Programinės įrangos kūrimas

9 klaidos, kurių reikia vengti programuojant "Java" kalba

Kokių klaidų reikėtų vengti programuojant "Java" kalba? Šiame straipsnyje atsakysime į šį klausimą.

The Codest
Rafal Sawicki "Java" programuotojas
Įmonių ir didinimo sprendimai

Tinkamas būdas rasti geriausius "Java" programuotojus

Rasti puikų "Java" programuotoją gali būti nelengva užduotis. Kadangi tokių specialistų paklausa rinkoje auga stulbinamai sparčiai, kartais gali atrodyti, kad turimi talentų paieškos šaltiniai...

The Codest
Grzegorz Rozmus "Java" padalinio vadovas
Įmonių ir didinimo sprendimai

Kaip "Java" gali padėti jūsų verslui?

Sužinokite, kaip "Java" ir "Java" virtualioji mašina (JVM) padeda kurti stabilią, keičiamo mastelio verslo programinę įrangą ir kada verta rinktis "Java".

Bartlomiejus Kučinskis
Įmonių ir didinimo sprendimai

The Codest programuotojo gyvenimo diena

Galite įtarti, kad programuotojų darbo grafikai nesiskiria vienas nuo kito. Tačiau iš tikrųjų tai netiesa! Kiekvienas startuolis, programinės įrangos įmonė ar net korporacija turi savo...

The Codest
Pawel Rybczynski Software Engineer

Prenumeruokite mūsų žinių bazę ir būkite nuolat informuoti apie IT sektoriaus patirtį.

    Apie mus

    The Codest - tarptautinė programinės įrangos kūrimo bendrovė, turinti technologijų centrus Lenkijoje.

    Jungtinė Karalystė - būstinė

    • 303B biuras, 182-184 High Street North E6 2JA
      Londonas, Anglija

    Lenkija - vietiniai technologijų centrai

    • Fabryczna biurų parkas, Aleja
      Pokoju 18, 31-564 Krokuva
    • Brain Embassy, Konstruktorska
      11, 02-673 Varšuva, Lenkija

      The Codest

    • Pagrindinis
    • Apie mus
    • Paslaugos
    • Case Studies
    • Sužinokite, kaip
    • Karjera
    • Žodynas

      Paslaugos

    • Patariamoji tarnyba
    • Programinės įrangos kūrimas
    • Galinės dalies kūrimas
    • Priekinės dalies kūrimas
    • Staff Augmentation
    • Atgalinės versijos kūrėjai
    • Debesų inžinieriai
    • Duomenų inžinieriai
    • Kita
    • QA inžinieriai

      Ištekliai

    • Faktai ir mitai apie bendradarbiavimą su išoriniu programinės įrangos kūrimo partneriu
    • Iš JAV į Europą: Kodėl Amerikos startuoliai nusprendžia persikelti į Europą?
    • Technikos plėtros centrų užsienyje palyginimas: Tech Offshore Europa (Lenkija), ASEAN (Filipinai), Eurazija (Turkija)
    • Kokie yra svarbiausi CTO ir CIO iššūkiai?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Autorinės teisės © 2026 The Codest. Visos teisės saugomos.

    lt_LTLithuanian
    en_USEnglish de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic it_ITItalian es_ESSpanish nl_NLDutch etEstonian elGreek pt_PTPortuguese cs_CZCzech lvLatvian lt_LTLithuanian