window.pipedriveLeadboosterConfig = { base: pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = window if (w.LeadBooster) { console.warn('LeadBooster on jo olemassa') } else { w.LeadBooster = { q: [], on: function (n, h) { this.q.push({ t: 'o', n: n, h: h }) }, trigger: function (n) { this.q.push({ t: 't', n: n }) }, } } })() Rinnakkaisuus Javassa Osa 1 - Johdanto - The Codest
Codest
  • Tietoa meistä
  • Palvelut
    • Ohjelmistokehitys
      • Frontend-kehitys
      • Backend-kehitys
    • Staff Augmentation
      • Frontend-kehittäjät
      • Backend-kehittäjät
      • Tietoinsinöörit
      • Pilvi-insinöörit
      • QA insinöörit
      • Muut
    • Se neuvoa-antava
      • Tilintarkastus & konsultointi
  • Toimialat
    • Fintech & pankkitoiminta
    • E-commerce
    • Adtech
    • Terveysteknologia
    • Valmistus
    • Logistiikka
    • Autoteollisuus
    • IOT
  • Arvo
    • TOIMITUSJOHTAJA
    • CTO
    • Toimituspäällikkö
  • Tiimimme
  • Tapaustutkimukset
  • Tiedä miten
    • Blogi
    • Tapaamiset
    • Webinaarit
    • Resurssit
Työurat Ota yhteyttä
  • Tietoa meistä
  • Palvelut
    • Ohjelmistokehitys
      • Frontend-kehitys
      • Backend-kehitys
    • Staff Augmentation
      • Frontend-kehittäjät
      • Backend-kehittäjät
      • Tietoinsinöörit
      • Pilvi-insinöörit
      • QA insinöörit
      • Muut
    • Se neuvoa-antava
      • Tilintarkastus & konsultointi
  • Arvo
    • TOIMITUSJOHTAJA
    • CTO
    • Toimituspäällikkö
  • Tiimimme
  • Tapaustutkimukset
  • Tiedä miten
    • Blogi
    • Tapaamiset
    • Webinaarit
    • Resurssit
Työurat Ota yhteyttä
Takaisin nuoli PALAA TAAKSE
2022-06-15
Ohjelmistokehitys

Rinnakkaisuus Javassa Osa 1 - Johdanto

Codest

Rafal Sawicki

Java-kehittäjä

Lue ensimmäinen osa blogisarjastamme, joka on omistettu rinnakkaisuudelle Javassa. Seuraavassa artikkelissa tarkastelemme tarkemmin säikeiden ja prosessien välisiä eroja, säiepooleja, suorittajia ja paljon muuta!

Yleisesti ottaen perinteinen ohjelmointitapa on peräkkäinen. Kaikki ohjelmassa tapahtuu yksi vaihe kerrallaan.
Itse asiassa koko maailma toimii rinnakkain - se on kyky suorittaa useampi kuin yksi tehtävä samanaikaisesti.

Kierre vs. prosessi

Keskustelemme sellaisista edistyneistä aiheista kuin samanaikaisuus Java tai monisäikeistyksestä, meidän on sovittava joistakin yhteisistä määritelmistä, jotta voimme olla varmoja siitä, että olemme samalla sivulla.

Aloitetaan perusasioista. Ei-sekventiaalisessa maailmassa meillä on kahdenlaisia samanaikaisuuden edustajia: prosessit ja
langat. Prosessi on käynnissä olevan ohjelman instanssi. Tavallisesti se on eristetty muista prosesseista.
Käyttöjärjestelmä vastaa resurssien osoittamisesta kullekin prosessille. Lisäksi se toimii johtimena, joka
aikataulut ja valvoo niitä.

Lanka on eräänlainen prosessi, mutta alemmalla tasolla, joten sitä kutsutaan myös kevyeksi langaksi. Useita säikeitä voi toimia yhdessä
prosessi. Ohjelma toimii tässä tapauksessa säikeiden aikatauluttajana ja ohjaajana. Näin yksittäiset ohjelmat näyttävät tekevän
useita tehtäviä samanaikaisesti.

Säikeiden ja prosessien välinen perusero on eristystaso. Prosessilla on oma joukkonsa
resursseja, kun taas säie jakaa tietoja muiden säikeiden kanssa. Lähestymistapa saattaa vaikuttaa virhealttiilta, ja sitä se myös on. Esimerkiksi
Nyt ei keskitytä siihen, sillä se ei kuulu tähän artikkeliin.

Prosessit, säikeet - okei... Mutta mitä rinnakkaisuus oikeastaan on? Rinnakkaisuus tarkoittaa, että voit suorittaa useita tehtäviä samanaikaisesti.
aika. Se ei tarkoita, että tehtävien on suorituttava samanaikaisesti - sitä rinnakkaisuus on. Concurrenc in Javay ei myöskään
vaativat useita suorittimia tai jopa useita ytimiä. Se voidaan toteuttaa yhden ytimen ympäristössä hyödyntämällä seuraavia keinoja
kontekstin vaihtaminen.

Samanaikaisuuteen liittyvä termi on monisäikeistäminen. Se on ohjelmien ominaisuus, jonka avulla ne voivat suorittaa useita tehtäviä samanaikaisesti. Kaikki ohjelmat eivät käytä tätä lähestymistapaa, mutta niitä, jotka käyttävät sitä, voidaan kutsua monisäikeisiksi.

Olemme melkein valmiita lähtemään, enää yksi määritelmä. Asynkronisuus tarkoittaa, että ohjelma suorittaa muita kuin lukkiutumattomia toimintoja.
Se käynnistää tehtävän ja jatkaa sitten muita asioita odottaessaan vastausta. Kun se saa vastauksen, se voi reagoida siihen.

Kaikki se jazz

Oletusarvoisesti jokainen Java-sovellus toimii yhdessä prosessissa. Tässä prosessissa on yksi säie, joka liittyy ohjelmaan main() menetelmä
hakemus. Kuten mainittu, on kuitenkin mahdollista hyödyntää useiden säikeiden mekanismeja yhdessä sovelluksessa.
ohjelma.

Käynnistettävä

Lanka on Java luokka, jossa taika tapahtuu. Tämä on edellä mainitun säikeen esitys. Osoitteeseen
luoda oman säikeen, voit laajentaa Lanka luokka. Sitä ei kuitenkaan suositella. Kierteet olisi käytettävä mekanismina, joka suorittaa tehtävän. Tehtävät ovat osia koodi jota haluamme ajaa rinnakkaistilassa. Voimme määritellä ne käyttämällä Käynnistettävä rajapinta.

Mutta teoria riittää, laitetaanpa koodimme sinne, missä suumme on.

Ongelma

Oletetaan, että meillä on pari numeromäärää. Haluamme tietää kunkin matriisin numeroiden summan. Olkoon
Teeskennellään, että tällaisia matriiseja on paljon ja että jokainen niistä on suhteellisen suuri. Tällaisessa tilanteessa haluamme hyödyntää samanaikaisuutta ja laskea jokaisen matriisin yhteen erillisenä tehtävänä.

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};
int[] a3 = {3, 4, 3, 4, 3, 4, 2, 1, 3, 7};

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

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

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

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

Kuten yllä olevasta koodista näkyy Käynnistettävä on toiminnallinen käyttöliittymä. Se sisältää yhden abstraktin menetelmän run()
ilman argumentteja. Osoite Käynnistettävä rajapinnan tulisi olla toteutettuna kaikissa luokissa, joiden instanssit on tarkoitettu olemaan
säikeen suorittama.

Kun olet määritellyt tehtävän, voit luoda säikeen sen suorittamista varten. Tämä onnistuu uusi säie() konstruktori, joka
ottaa Käynnistettävä sen argumenttina.

Viimeinen vaihe on start() äskettäin luotu säie. API:ssa on myös run() menetelmät Käynnistettävä ja
Lanka. Se ei kuitenkaan ole tapa hyödyntää samanaikaisuutta Javassa. Suora kutsu kuhunkin näistä metodeista johtaa tulokseen
tehtävän suorittaminen samassa säikeessä, jossa main() menetelmä toimii.

Säiepoolit ja toteuttajat

Kun tehtäviä on paljon, erillisen säikeen luominen jokaista tehtävää varten ei ole hyvä idea. Luominen Lanka on
raskas operaatio, ja on paljon parempi käyttää olemassa olevia säikeitä uudelleen kuin luoda uusia.

Kun ohjelma luo monia lyhytikäisiä säikeitä, on parempi käyttää säiepoolia. Säiepooli sisältää useita
käyttövalmiita mutta tällä hetkellä ei aktiivisia säikeitä. Antamalla Käynnistettävä pooliin aiheuttaa sen, että yksi säikeistä kutsuu komentoa
run() menetelmä tietyn Käynnistettävä. Tehtävän suorittamisen jälkeen säie on edelleen olemassa ja joutokäyntitilassa.

Okei, ymmärrät kyllä - mieluummin säiepooli kuin manuaalinen luominen. Mutta miten voit hyödyntää säiepooleja? Osoitteessa Toimeenpanijat
luokassa on useita staattisia tehdasmenetelmiä säiepoolien rakentamista varten. Esimerkiksi newCachedThredPool() luo
pooli, johon luodaan uusia säikeitä tarpeen mukaan ja tyhjänä olevia säikeitä pidetään 60 sekunnin ajan. Sitä vastoin,
newFixedThreadPool() sisältää kiinteän joukon säikeitä, joissa käyttämättömiä säikeitä säilytetään loputtomiin.

Katsotaanpa, miten se voisi toimia esimerkissämme. Nyt meidän ei tarvitse luoda säikeitä manuaalisesti. Sen sijaan meidän on luotava
ExecutorService joka tarjoaa säikeiden varannon. Sitten voimme antaa sille tehtäviä. Viimeinen vaihe on säikeen sulkeminen
poolia muistivuodon välttämiseksi. Muu osa edellisestä koodista pysyy samana.

ExecutorService executor = Executors.newCachedThreadPool();

executor.submit(task1);
executor.submit(tehtävä2);
executor.submit(task3);

executor.shutdown();

Soitettavissa

Käynnistettävä vaikuttaa näppärältä tavalta luoda samanaikaisia tehtäviä, mutta siinä on yksi merkittävä puute. Se ei voi palauttaa mitään
arvo. Lisäksi emme voi määrittää, onko tehtävä suoritettu vai ei. Emme myöskään tiedä, onko se suoritettu loppuun.
normaalisti tai poikkeuksellisesti. Ratkaisu näihin epäkohtiin on Soitettavissa.

Soitettavissa on samanlainen kuin Käynnistettävä tavallaan myös asynkronisia tehtäviä. Tärkein ero on, että se pystyy
palauttaa arvon. Paluuarvo voi olla mitä tahansa (ei-primitiivistä) tyyppiä, kuten esimerkki Soitettavissa rajapinta on parametrisoitu tyyppi.
Soitettavissa on toiminnallinen käyttöliittymä, jolla on call() menetelmä, joka voi heittää Poikkeus.

Katsotaanpa nyt, miten voimme hyödyntää Soitettavissa joukko-ongelmassamme.

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};
int[] a3 = {3, 4, 3, 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. Summa on: " + future1.get());
System.out.println("2. Summa on: " + future2.get());
System.out.println("3. Summa on: " + future3.get());

executor.shutdown();

Okei, näemme miten Soitettavissa luodaan ja lähetetään sitten ExecutorService. Mutta mitä hemmettiä on Tulevaisuus?
Tulevaisuus toimii siltana säikeiden välillä. Kunkin matriisin summa tuotetaan erillisessä säikeessä, ja tarvitsemme keinon, jolla voimme
saada nämä tulokset takaisin main().

Tuloksen hakeminen osoitteesta Tulevaisuus meidän on soitettava get() menetelmä. Tässä voi tapahtua jompikumpi kahdesta asiasta. Ensinnäkin
laskennan tulos, jonka suorittaa Soitettavissa on saatavilla. Sitten saamme sen välittömästi. Toiseksi, tulos ei ole
valmis vielä. Siinä tapauksessa get() metodi estyy, kunnes tulos on saatavilla.

ComputableFuture

Kysymys Tulevaisuus on, että se toimii "push-paradigman" mukaisesti. Kun käytetään Tulevaisuus sinun on oltava kuin pomo, joka
kysyy jatkuvasti: "Onko tehtäväsi suoritettu? Onko se valmis?', kunnes se tuottaa tuloksen. Jatkuvan paineen alla toimiminen on
kallista. Paljon parempi lähestymistapa olisi tilata Tulevaisuus mitä tehdä, kun se on valmis tehtäväänsä. Valitettavasti,
Tulevaisuus ei voi tehdä sitä, mutta ComputableFuture voi.

ComputableFuture toimii 'pull-paradigmassa'. Voimme kertoa sille, mitä tehdä tuloksella, kun se on suorittanut tehtävänsä. Se
on esimerkki asynkronisesta lähestymistavasta.

ComputableFuture toimii täydellisesti Käynnistettävä mutta ei Soitettavissa. Sen sijaan on mahdollista antaa tehtävä osoitteeseen
ComputableFuture muodossa Toimittaja.

Katsotaanpa, miten edellä mainittu liittyy ongelmaamme.

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};
int[] a3 = {3, 4, 3, 4, 3, 4, 2, 1, 3, 7};

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

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

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

Ensimmäisenä silmiinpistävänä asiana on, kuinka paljon lyhyempi tämä ratkaisu on. Sen lisäksi se näyttää myös siistiltä ja siistiltä.

Tehtävä CompletableFuture voi antaa supplyAsync() menetelmä, joka ottaa Toimittaja tai runAsync() että
ottaa Käynnistettävä. Takaisinkutsu - koodinpätkä, joka on suoritettava tehtävän päättyessä - määritellään seuraavasti thenAccept()
menetelmä.

Päätelmät

Java tarjoaa paljon erilaisia lähestymistapoja samanaikaisuuteen. Tässä artikkelissa käsittelimme aihetta hädin tuskin.

Käsittelimme kuitenkin perusasiat, jotka koskevat Lanka, Käynnistettävä, Soitettavissaja CallableFuture mikä on hyvä seikka
aiheen jatkotutkimusta varten.

Aiheeseen liittyvät artikkelit

Ohjelmistokehitys

9 virhettä, joita kannattaa välttää Java-ohjelmoinnissa

Mitä virheitä tulisi välttää Java-ohjelmoinnissa? Seuraavassa kappaleessa vastaamme tähän kysymykseen.

Codest
Rafal Sawicki Java-kehittäjä
Yritys- ja skaalausratkaisut

Oikea tapa löytää parhaat Java-kehittäjät

Täydellisen Java-kehittäjän löytäminen voi olla pelottava tehtävä. Koska tällaisten ammattilaisten markkinakysyntä kasvaa hämmästyttävää vauhtia, käytettävissä olevat lähteet lahjakkuuksien etsimiseen voivat joskus tuntua...

Codest
Grzegorz Rozmus Java-yksikön johtaja
Yritys- ja skaalausratkaisut

10 Dubain yritystä, joita kannattaa tarkkailla vuonna 2020

Dubai on Yhdistyneiden arabiemiirikuntien sydän, jossa on yhä vauraammat maailmanlaajuisten yritysten ja lupaavien startup-yritysten markkinat. Monet voivat ylpeillä kansainvälisellä menestyksellään ja huomionarvoisilla tuotteillaan.....

Tuna Pinar
Yritys- ja skaalausratkaisut

Miten Java voi tukea yritystäsi?

Ennen kuin aloitamme, haluaisin muistuttaa teitä yhdestä tärkeästä asiasta. Java ei ole vain ohjelmointikieli.

Bartlomiej Kuczynski
Yritys- ja skaalausratkaisut

Päivä ohjelmoijan elämässä The Codest:ssä

Saatat epäillä, että ohjelmoijien työaikataulut eivät eroa toisistaan. Tämä ei kuitenkaan pidä paikkaansa! Jokaisella startup-yrityksellä, ohjelmistotalolla ja jopa yrityksellä on omat...

Codest
Pawel Rybczynski Software Engineer

Tilaa tietopankkimme ja pysy ajan tasalla IT-alan asiantuntemuksesta.

    Tietoa meistä

    The Codest - Kansainvälinen ohjelmistokehitysyritys, jolla on teknologiakeskuksia Puolassa.

    Yhdistynyt kuningaskunta - pääkonttori

    • Toimisto 303B, 182-184 High Street North E6 2JA
      Lontoo, Englanti

    Puola - Paikalliset teknologiakeskukset

    • Fabryczna Office Park, Aleja
      Pokoju 18, 31-564 Krakova
    • Brain Embassy, Konstruktorska
      11, 02-673 Varsova, Puola

      Codest

    • Etusivu
    • Tietoa meistä
    • Palvelut
    • Tapaustutkimukset
    • Tiedä miten
    • Työurat
    • Sanakirja

      Palvelut

    • Se neuvoa-antava
    • Ohjelmistokehitys
    • Backend-kehitys
    • Frontend-kehitys
    • Staff Augmentation
    • Backend-kehittäjät
    • Pilvi-insinöörit
    • Tietoinsinöörit
    • Muut
    • QA insinöörit

      Resurssit

    • Faktoja ja myyttejä yhteistyöstä ulkoisen ohjelmistokehityskumppanin kanssa
    • Yhdysvalloista Eurooppaan: Miksi amerikkalaiset startup-yritykset päättävät muuttaa Eurooppaan?
    • Tech Offshore -kehityskeskusten vertailu: Tech Offshore Eurooppa (Puola), ASEAN (Filippiinit), Euraasia (Turkki).
    • Mitkä ovat teknologiajohtajien ja tietohallintojohtajien tärkeimmät haasteet?
    • Codest
    • Codest
    • Codest
    • Privacy policy
    • Verkkosivuston käyttöehdot

    Tekijänoikeus © 2025 by The Codest. Kaikki oikeudet pidätetään.

    fiFinnish
    en_USEnglish de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fr_FRFrench pl_PLPolish arArabic it_ITItalian jaJapanese ko_KRKorean es_ESSpanish nl_NLDutch etEstonian elGreek fiFinnish