{"id":3138,"date":"2022-06-15T05:27:58","date_gmt":"2022-06-15T05:27:58","guid":{"rendered":"http:\/\/the-codest.localhost\/blog\/concurrency-in-java-part-1-introduction\/"},"modified":"2026-03-11T05:59:41","modified_gmt":"2026-03-11T05:59:41","slug":"samanaikaisuus-java-osa-1-johdanto","status":"publish","type":"post","link":"https:\/\/thecodest.co\/fi\/blog\/concurrency-in-java-part-1-introduction\/","title":{"rendered":"Rinnakkaisuus Javassa Osa 1 - Johdanto"},"content":{"rendered":"<p>Yleisesti ottaen perinteinen ohjelmointitapa on per\u00e4kk\u00e4inen. Kaikki ohjelmassa tapahtuu yksi vaihe kerrallaan.<br>Itse asiassa koko maailma toimii rinnakkain - se on kyky suorittaa useampi kuin yksi teht\u00e4v\u00e4 samanaikaisesti.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Kierre vs. prosessi<\/h2>\n\n\n\n<p>Keskustelemme sellaisista edistyneist\u00e4 aiheista kuin <strong>samanaikaisuus <a href=\"https:\/\/thecodest.co\/fi\/blog\/top-programming-languages-to-build-e-commerce\/\">Java<\/a><\/strong> tai monis\u00e4ikeistyksest\u00e4, meid\u00e4n on sovittava joistakin yhteisist\u00e4 m\u00e4\u00e4ritelmist\u00e4, jotta voimme olla varmoja siit\u00e4, ett\u00e4 olemme samalla sivulla.<\/p>\n\n\n\n<p>Aloitetaan perusasioista. Ei-sekventiaalisessa maailmassa meill\u00e4 on kahdenlaisia samanaikaisuuden edustajia: prosessit ja<br>langat. Prosessi on k\u00e4ynniss\u00e4 olevan ohjelman instanssi. Tavallisesti se on eristetty muista prosesseista.<br>K\u00e4ytt\u00f6j\u00e4rjestelm\u00e4 vastaa resurssien osoittamisesta kullekin prosessille. Lis\u00e4ksi se toimii johtimena, joka<br>aikataulut ja valvoo niit\u00e4.<\/p>\n\n\n\n<p>Lanka on er\u00e4\u00e4nlainen prosessi, mutta alemmalla tasolla, joten sit\u00e4 kutsutaan my\u00f6s kevyeksi langaksi. Useita s\u00e4ikeit\u00e4 voi toimia yhdess\u00e4<br>prosessi. Ohjelma toimii t\u00e4ss\u00e4 tapauksessa s\u00e4ikeiden aikatauluttajana ja ohjaajana. N\u00e4in yksitt\u00e4iset ohjelmat n\u00e4ytt\u00e4v\u00e4t tekev\u00e4n<br>useita teht\u00e4vi\u00e4 samanaikaisesti.<\/p>\n\n\n\n<p>S\u00e4ikeiden ja prosessien v\u00e4linen perusero on eristystaso. Prosessilla on oma joukkonsa<br>resursseja, kun taas s\u00e4ie jakaa <a href=\"https:\/\/thecodest.co\/fi\/blog\/app-data-collection-security-risks-value-and-types-explored\/\">tiedot<\/a> muiden s\u00e4ikeiden kanssa. T\u00e4m\u00e4 saattaa vaikuttaa virhealttiilta l\u00e4hestymistavalta, ja sit\u00e4 se my\u00f6s on. Sill\u00e4<br>Nyt ei keskityt\u00e4 siihen, sill\u00e4 se ei kuulu t\u00e4h\u00e4n artikkeliin.<\/p>\n\n\n\n<p>Prosessit, s\u00e4ikeet - okei... Mutta mit\u00e4 rinnakkaisuus oikeastaan on? Rinnakkaisuus tarkoittaa, ett\u00e4 voit suorittaa useita teht\u00e4vi\u00e4 samanaikaisesti.<br>aika. Se ei tarkoita, ett\u00e4 teht\u00e4vien on suorituttava samanaikaisesti - sit\u00e4 rinnakkaisuus on. <strong>Concurrenc in Javay<\/strong> ei my\u00f6sk\u00e4\u00e4n<br>vaativat useita suorittimia tai jopa useita ytimi\u00e4. Se voidaan toteuttaa yhden ytimen ymp\u00e4rist\u00f6ss\u00e4 hy\u00f6dynt\u00e4m\u00e4ll\u00e4 seuraavia keinoja<br>kontekstin vaihtaminen.<\/p>\n\n\n\n<p>Samanaikaisuuteen liittyv\u00e4 termi on monis\u00e4ikeist\u00e4minen. Se on ohjelmien ominaisuus, jonka avulla ne voivat suorittaa useita teht\u00e4vi\u00e4 samanaikaisesti. Kaikki ohjelmat eiv\u00e4t k\u00e4yt\u00e4 t\u00e4t\u00e4 l\u00e4hestymistapaa, mutta niit\u00e4, jotka k\u00e4ytt\u00e4v\u00e4t sit\u00e4, voidaan kutsua monis\u00e4ikeisiksi.<\/p>\n\n\n\n<p>Olemme melkein valmiita l\u00e4htem\u00e4\u00e4n, en\u00e4\u00e4 yksi m\u00e4\u00e4ritelm\u00e4. Asynkronisuus tarkoittaa, ett\u00e4 ohjelma suorittaa muita kuin lukkiutumattomia toimintoja.<br>Se k\u00e4ynnist\u00e4\u00e4 teht\u00e4v\u00e4n ja jatkaa sitten muita asioita odottaessaan vastausta. Kun se saa vastauksen, se voi <a href=\"https:\/\/thecodest.co\/fi\/blog\/react-development-all-you-have-to-know\/\">reagoida<\/a> siihen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Kaikki se jazz<\/h2>\n\n\n\n<p>Oletusarvoisesti jokainen <strong>Java-sovellus<\/strong> toimii yhdess\u00e4 prosessissa. T\u00e4ss\u00e4 prosessissa on yksi s\u00e4ie, joka liittyy ohjelmaan <code>main()<\/code> menetelm\u00e4<br>hakemus. Kuten mainittu, on kuitenkin mahdollista hy\u00f6dynt\u00e4\u00e4 useiden s\u00e4ikeiden mekanismeja yhdess\u00e4 sovelluksessa.<br>ohjelma.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">K\u00e4ynnistett\u00e4v\u00e4<\/h3>\n\n\n\n<p><code>Lanka<\/code> on <strong>Java<\/strong> luokka, jossa taika tapahtuu. T\u00e4m\u00e4 on edell\u00e4 mainitun s\u00e4ikeen esitys. Osoitteeseen<br>luoda oman s\u00e4ikeen, voit laajentaa <code>Lanka<\/code> luokka. Sit\u00e4 ei kuitenkaan suositella. <code>Kierteet<\/code> olisi k\u00e4ytett\u00e4v\u00e4 mekanismina, joka suorittaa teht\u00e4v\u00e4n. Teht\u00e4v\u00e4t ovat osia <a href=\"https:\/\/thecodest.co\/fi\/dictionary\/what-is-code-refactoring\/\">koodi<\/a> jota haluamme ajaa rinnakkaistilassa. Voimme m\u00e4\u00e4ritell\u00e4 ne k\u00e4ytt\u00e4m\u00e4ll\u00e4 <code>K\u00e4ynnistett\u00e4v\u00e4<\/code> rajapinta.<\/p>\n\n\n\n<p>Mutta teoria riitt\u00e4\u00e4, laitetaanpa koodimme sinne, miss\u00e4 suumme on.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Ongelma<\/h3>\n\n\n\n<p>Oletetaan, ett\u00e4 meill\u00e4 on pari numerom\u00e4\u00e4r\u00e4\u00e4. Haluamme tiet\u00e4\u00e4 kunkin matriisin numeroiden summan. Olkoon<br>Teeskennell\u00e4\u00e4n, ett\u00e4 t\u00e4llaisia matriiseja on paljon ja ett\u00e4 jokainen niist\u00e4 on suhteellisen suuri. T\u00e4llaisessa tilanteessa haluamme hy\u00f6dynt\u00e4\u00e4 samanaikaisuutta ja laskea jokaisen matriisin yhteen erillisen\u00e4 teht\u00e4v\u00e4n\u00e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">int[] a1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\nint[] a2 = {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10};\nint[] a3 = {3, 4, 3, 4, 3, 4, 2, 1, 3, 7};\n\nRunnable task1 = () -&gt; { {\n    int sum = Arrays.stream(a1).sum();\n    System.out.println(\"1. Summa on: \" + sum);\n};\n\nRunnable task2 = () -&gt; { {\n    int sum = Arrays.stream(a2).sum();\n    System.out.println(\"2. Summa on: \" + sum);\n};\n\nRunnable task3 = () -&gt; { {\n    int sum = Arrays.stream(a3).sum();\n    System.out.println(\"3. Summa on: \" + sum);\n};\n\nnew Thread(task1).start();\nnew Thread(task2).start();\nnew Thread(task3).start();<\/code><\/pre>\n\n\n\n<p>Kuten yll\u00e4 olevasta koodista n\u00e4kyy <code>K\u00e4ynnistett\u00e4v\u00e4<\/code> on toiminnallinen k\u00e4ytt\u00f6liittym\u00e4. Se sis\u00e4lt\u00e4\u00e4 yhden abstraktin menetelm\u00e4n <code>run()<\/code><br>ilman argumentteja. Osoite <code>K\u00e4ynnistett\u00e4v\u00e4<\/code> rajapinnan tulisi olla toteutettuna kaikissa luokissa, joiden instanssit on tarkoitettu olemaan<br>s\u00e4ikeen suorittama.<\/p>\n\n\n\n<p>Kun olet m\u00e4\u00e4ritellyt teht\u00e4v\u00e4n, voit luoda s\u00e4ikeen sen suorittamista varten. T\u00e4m\u00e4 onnistuu <code>uusi s\u00e4ie()<\/code> konstruktori, joka<br>ottaa <code>K\u00e4ynnistett\u00e4v\u00e4<\/code> sen argumenttina.<\/p>\n\n\n\n<p>Viimeinen vaihe on <code>start()<\/code> \u00e4skett\u00e4in luotu s\u00e4ie. Kohdassa <a href=\"https:\/\/thecodest.co\/fi\/blog\/compare-staff-augmentation-firms-that-excel-in-api-team-staffing-for-financial-technology-projects\/\">API<\/a> on my\u00f6s <code>run()<\/code> menetelm\u00e4t <code>K\u00e4ynnistett\u00e4v\u00e4<\/code> ja<br><code>Lanka<\/code>. Se ei kuitenkaan ole tapa hy\u00f6dynt\u00e4\u00e4 samanaikaisuutta Javassa. Suora kutsu kuhunkin n\u00e4ist\u00e4 metodeista johtaa tulokseen<br>teht\u00e4v\u00e4n suorittaminen samassa s\u00e4ikeess\u00e4, jossa <code>main()<\/code> menetelm\u00e4 toimii.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">S\u00e4iepoolit ja toteuttajat<\/h3>\n\n\n\n<p>Kun teht\u00e4vi\u00e4 on paljon, erillisen s\u00e4ikeen luominen jokaista teht\u00e4v\u00e4\u00e4 varten ei ole hyv\u00e4 idea. Luominen <code>Lanka<\/code> on<br>raskas operaatio, ja on paljon parempi k\u00e4ytt\u00e4\u00e4 olemassa olevia s\u00e4ikeit\u00e4 uudelleen kuin luoda uusia.<\/p>\n\n\n\n<p>Kun ohjelma luo monia lyhytik\u00e4isi\u00e4 s\u00e4ikeit\u00e4, on parempi k\u00e4ytt\u00e4\u00e4 s\u00e4iepoolia. S\u00e4iepooli sis\u00e4lt\u00e4\u00e4 useita<br>k\u00e4ytt\u00f6valmiita mutta t\u00e4ll\u00e4 hetkell\u00e4 ei aktiivisia s\u00e4ikeit\u00e4. Antamalla <code>K\u00e4ynnistett\u00e4v\u00e4<\/code> pooliin aiheuttaa sen, ett\u00e4 yksi s\u00e4ikeist\u00e4 kutsuu komentoa<br><code>run()<\/code> menetelm\u00e4 tietyn <code>K\u00e4ynnistett\u00e4v\u00e4<\/code>. Teht\u00e4v\u00e4n suorittamisen j\u00e4lkeen s\u00e4ie on edelleen olemassa ja joutok\u00e4yntitilassa.<\/p>\n\n\n\n<p>Okei, ymm\u00e4rr\u00e4t kyll\u00e4 - mieluummin s\u00e4iepooli kuin manuaalinen luominen. Mutta miten voit hy\u00f6dynt\u00e4\u00e4 s\u00e4iepooleja? Osoitteessa <code>Toimeenpanijat<\/code><br>luokassa on useita staattisia tehdasmenetelmi\u00e4 s\u00e4iepoolien rakentamista varten. Esimerkiksi <code>newCachedThredPool()<\/code> luo<br>pooli, johon luodaan uusia s\u00e4ikeit\u00e4 tarpeen mukaan ja tyhj\u00e4n\u00e4 olevia s\u00e4ikeit\u00e4 pidet\u00e4\u00e4n 60 sekunnin ajan. Sit\u00e4 vastoin,<br><code>newFixedThreadPool()<\/code> sis\u00e4lt\u00e4\u00e4 kiinte\u00e4n joukon s\u00e4ikeit\u00e4, joissa k\u00e4ytt\u00e4m\u00e4tt\u00f6mi\u00e4 s\u00e4ikeit\u00e4 s\u00e4ilytet\u00e4\u00e4n loputtomiin.<\/p>\n\n\n\n<p>Katsotaanpa, miten se voisi toimia esimerkiss\u00e4mme. Nyt meid\u00e4n ei tarvitse luoda s\u00e4ikeit\u00e4 manuaalisesti. Sen sijaan meid\u00e4n on luotava<br><code>ExecutorService<\/code> joka tarjoaa s\u00e4ikeiden varannon. Sitten voimme antaa sille teht\u00e4vi\u00e4. Viimeinen vaihe on s\u00e4ikeen sulkeminen<br>poolia muistivuodon v\u00e4ltt\u00e4miseksi. Muu osa edellisest\u00e4 koodista pysyy samana.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">ExecutorService executor = Executors.newCachedThreadPool();\n\nexecutor.submit(task1);\nexecutor.submit(teht\u00e4v\u00e42);\nexecutor.submit(task3);\n\nexecutor.shutdown();<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Soitettavissa<\/h3>\n\n\n\n<p><code>K\u00e4ynnistett\u00e4v\u00e4<\/code> vaikuttaa n\u00e4pp\u00e4r\u00e4lt\u00e4 tavalta luoda samanaikaisia teht\u00e4vi\u00e4, mutta siin\u00e4 on yksi merkitt\u00e4v\u00e4 puute. Se ei voi palauttaa mit\u00e4\u00e4n<br>arvo. Lis\u00e4ksi emme voi m\u00e4\u00e4ritt\u00e4\u00e4, onko teht\u00e4v\u00e4 suoritettu vai ei. Emme my\u00f6sk\u00e4\u00e4n tied\u00e4, onko se suoritettu loppuun.<br>normaalisti tai poikkeuksellisesti. Ratkaisu n\u00e4ihin ep\u00e4kohtiin on <code>Soitettavissa<\/code>.<\/p>\n\n\n\n<p><code>Soitettavissa<\/code> on samanlainen kuin <code>K\u00e4ynnistett\u00e4v\u00e4<\/code> tavallaan my\u00f6s asynkronisia teht\u00e4vi\u00e4. T\u00e4rkein ero on, ett\u00e4 se pystyy<br>palauttaa arvon. Paluuarvo voi olla mit\u00e4 tahansa (ei-primitiivist\u00e4) tyyppi\u00e4, kuten esimerkki <code>Soitettavissa<\/code> rajapinta on parametrisoitu tyyppi.<br><code>Soitettavissa<\/code> on toiminnallinen k\u00e4ytt\u00f6liittym\u00e4, jolla on <code>call()<\/code> menetelm\u00e4, joka voi heitt\u00e4\u00e4 <code>Poikkeus<\/code>.<\/p>\n\n\n\n<p>Katsotaanpa nyt, miten voimme hy\u00f6dynt\u00e4\u00e4 <code>Soitettavissa<\/code> joukko-ongelmassamme.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">int[] a1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\nint[] a2 = {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10};\nint[] a3 = {3, 4, 3, 4, 3, 4, 2, 1, 3, 7};\n\nCallable task1 = () -&gt; Arrays.stream(a1).sum();\nCallable task2 = () -&gt; Arrays.stream(a2).sum();\nCallable task3 = () -&gt; Arrays.stream(a3).sum();\n\nExecutorService executor = Executors.newCachedThreadPool();\nFuture future1 = executor.submit(task1);\nFuture future2 = executor.submit(task2);\nFuture future3 = executor.submit(task3);\n\nSystem.out.println(\"1. Summa on: \" + future1.get());\nSystem.out.println(\"2. Summa on: \" + future2.get());\nSystem.out.println(\"3. Summa on: \" + future3.get());\n\nexecutor.shutdown();<\/code><\/pre>\n\n\n\n<p>Okei, n\u00e4emme miten <code>Soitettavissa<\/code> luodaan ja l\u00e4hetet\u00e4\u00e4n sitten <code>ExecutorService<\/code>. Mutta mit\u00e4 hemmetti\u00e4 on <code>Tulevaisuus<\/code>?<br><code>Tulevaisuus<\/code> toimii siltana s\u00e4ikeiden v\u00e4lill\u00e4. Kunkin matriisin summa tuotetaan erillisess\u00e4 s\u00e4ikeess\u00e4, ja tarvitsemme keinon, jolla voimme<br>saada n\u00e4m\u00e4 tulokset takaisin <code>main()<\/code>.<\/p>\n\n\n\n<p>Tuloksen hakeminen osoitteesta <code>Tulevaisuus<\/code> meid\u00e4n on soitettava <code>get()<\/code> menetelm\u00e4. T\u00e4ss\u00e4 voi tapahtua jompikumpi kahdesta asiasta. Ensinn\u00e4kin<br>laskennan tulos, jonka suorittaa <code>Soitettavissa<\/code> on saatavilla. Sitten saamme sen v\u00e4litt\u00f6m\u00e4sti. Toiseksi, tulos ei ole<br>valmis viel\u00e4. Siin\u00e4 tapauksessa <code>get()<\/code> metodi estyy, kunnes tulos on saatavilla.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">ComputableFuture<\/h3>\n\n\n\n<p>Kysymys <code>Tulevaisuus<\/code> on, ett\u00e4 se toimii \"push-paradigman\" mukaisesti. Kun k\u00e4ytet\u00e4\u00e4n <code>Tulevaisuus<\/code> sinun on oltava kuin pomo, joka<br>kysyy jatkuvasti: \"Onko teht\u00e4v\u00e4si suoritettu? Onko se valmis?', kunnes se tuottaa tuloksen. Jatkuvan paineen alla toimiminen on<br>kallista. Paljon parempi l\u00e4hestymistapa olisi tilata <code>Tulevaisuus<\/code> mit\u00e4 tehd\u00e4, kun se on valmis teht\u00e4v\u00e4\u00e4ns\u00e4. Valitettavasti,<br><code>Tulevaisuus<\/code> ei voi tehd\u00e4 sit\u00e4, mutta <code>ComputableFuture<\/code> voi.<\/p>\n\n\n\n<p><code>ComputableFuture<\/code> toimii 'pull-paradigmassa'. Voimme kertoa sille, mit\u00e4 tehd\u00e4 tuloksella, kun se on suorittanut teht\u00e4v\u00e4ns\u00e4. Se<br>on esimerkki asynkronisesta l\u00e4hestymistavasta.<\/p>\n\n\n\n<p><code>ComputableFuture<\/code> toimii t\u00e4ydellisesti <code>K\u00e4ynnistett\u00e4v\u00e4<\/code> mutta ei <code>Soitettavissa<\/code>. Sen sijaan on mahdollista antaa teht\u00e4v\u00e4 osoitteeseen<br><code>ComputableFuture<\/code> muodossa <code>Toimittaja<\/code>.<\/p>\n\n\n\n<p>Katsotaanpa, miten edell\u00e4 mainittu liittyy ongelmaamme.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">int[] a1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\nint[] a2 = {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10};\nint[] a3 = {3, 4, 3, 4, 3, 4, 2, 1, 3, 7};\n\nCompletableFuture.supplyAsync(() -&gt; Arrays.stream(a1).sum())\n                .thenAccept(System.out::println);\n\nCompletableFuture.supplyAsync(() -&gt; Arrays.stream(a2).summa())\n                .thenAccept(System.out::println);\n\nCompletableFuture.supplyAsync(() -&gt; Arrays.stream(a3).summa())\n                .thenAccept(System.out::println);<\/code><\/pre>\n\n\n\n<p>Ensimm\u00e4isen\u00e4 silmiinpist\u00e4v\u00e4n\u00e4 asiana on, kuinka paljon lyhyempi t\u00e4m\u00e4 ratkaisu on. Sen lis\u00e4ksi se n\u00e4ytt\u00e4\u00e4 my\u00f6s siistilt\u00e4 ja siistilt\u00e4.<\/p>\n\n\n\n<p>Teht\u00e4v\u00e4 <code>CompletableFuture<\/code> voi antaa <code>supplyAsync()<\/code> menetelm\u00e4, joka ottaa <code>Toimittaja<\/code> tai <code>runAsync()<\/code> ett\u00e4<br>ottaa <code>K\u00e4ynnistett\u00e4v\u00e4<\/code>. Takaisinkutsu - koodinp\u00e4tk\u00e4, joka on suoritettava teht\u00e4v\u00e4n p\u00e4\u00e4ttyess\u00e4 - m\u00e4\u00e4ritell\u00e4\u00e4n seuraavasti <code>thenAccept()<\/code><br>menetelm\u00e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">P\u00e4\u00e4telm\u00e4t<\/h2>\n\n\n\n<p><strong>Java<\/strong> tarjoaa paljon erilaisia l\u00e4hestymistapoja samanaikaisuuteen. T\u00e4ss\u00e4 artikkelissa k\u00e4sittelimme aihetta h\u00e4din tuskin.<\/p>\n\n\n\n<p>K\u00e4sittelimme kuitenkin perusasiat, jotka koskevat <code>Lanka<\/code>, <code>K\u00e4ynnistett\u00e4v\u00e4<\/code>, <code>Soitettavissa<\/code>ja <code>CallableFuture<\/code> mik\u00e4 on hyv\u00e4 seikka<br>aiheen jatkotutkimusta varten.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/thecodest.co\/contact\/\"><img loading=\"lazy\" decoding=\"async\" width=\"1283\" height=\"460\" src=\"https:\/\/thecodest.co\/app\/uploads\/2024\/05\/interested_in_cooperation_.png\" alt=\"\" class=\"wp-image-4927\" srcset=\"https:\/\/thecodest.co\/app\/uploads\/2024\/05\/interested_in_cooperation_.png 1283w, https:\/\/thecodest.co\/app\/uploads\/2024\/05\/interested_in_cooperation_-300x108.png 300w, https:\/\/thecodest.co\/app\/uploads\/2024\/05\/interested_in_cooperation_-1024x367.png 1024w, https:\/\/thecodest.co\/app\/uploads\/2024\/05\/interested_in_cooperation_-768x275.png 768w, https:\/\/thecodest.co\/app\/uploads\/2024\/05\/interested_in_cooperation_-18x6.png 18w, https:\/\/thecodest.co\/app\/uploads\/2024\/05\/interested_in_cooperation_-67x24.png 67w\" sizes=\"auto, (max-width: 1283px) 100vw, 1283px\" \/><\/a><\/figure>","protected":false},"excerpt":{"rendered":"<p>Lue ensimm\u00e4inen osa blogisarjastamme, joka on omistettu rinnakkaisuudelle Javassa. Seuraavassa artikkelissa tarkastelemme tarkemmin s\u00e4ikeiden ja prosessien v\u00e4lisi\u00e4 eroja, s\u00e4iepooleja, suorittajia ja paljon muuta!<\/p>","protected":false},"author":2,"featured_media":3139,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[8],"tags":[],"class_list":["post-3138","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-software-development"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.3 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Concurrency in Java Part 1 - Introduction - The Codest<\/title>\n<meta name=\"description\" content=\"Read the first part of our blog series devoted to concurrency in Java.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/thecodest.co\/fi\/blogi\/samanaikaisuus-java-osa-1-johdanto\/\" \/>\n<meta property=\"og:locale\" content=\"fi_FI\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Concurrency in Java Part 1 - Introduction\" \/>\n<meta property=\"og:description\" content=\"Read the first part of our blog series devoted to concurrency in Java.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/thecodest.co\/fi\/blogi\/samanaikaisuus-java-osa-1-johdanto\/\" \/>\n<meta property=\"og:site_name\" content=\"The Codest\" \/>\n<meta property=\"article:published_time\" content=\"2022-06-15T05:27:58+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-03-11T05:59:41+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/thecodest.co\/app\/uploads\/2024\/05\/concurrency_in_java_part_1_-_introduction.png\" \/>\n\t<meta property=\"og:image:width\" content=\"960\" \/>\n\t<meta property=\"og:image:height\" content=\"540\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"thecodest\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"thecodest\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/concurrency-in-java-part-1-introduction\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/concurrency-in-java-part-1-introduction\\\/\"},\"author\":{\"name\":\"thecodest\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/#\\\/schema\\\/person\\\/7e3fe41dfa4f4e41a7baad4c6e0d4f76\"},\"headline\":\"Concurrency in Java Part 1 &#8211; Introduction\",\"datePublished\":\"2022-06-15T05:27:58+00:00\",\"dateModified\":\"2026-03-11T05:59:41+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/concurrency-in-java-part-1-introduction\\\/\"},\"wordCount\":1295,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/concurrency-in-java-part-1-introduction\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/thecodest.co\\\/app\\\/uploads\\\/2024\\\/05\\\/concurrency_in_java_part_1_-_introduction.png\",\"articleSection\":[\"Software Development\"],\"inLanguage\":\"fi\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/thecodest.co\\\/blog\\\/concurrency-in-java-part-1-introduction\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/concurrency-in-java-part-1-introduction\\\/\",\"url\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/concurrency-in-java-part-1-introduction\\\/\",\"name\":\"Concurrency in Java Part 1 - Introduction - The Codest\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/concurrency-in-java-part-1-introduction\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/concurrency-in-java-part-1-introduction\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/thecodest.co\\\/app\\\/uploads\\\/2024\\\/05\\\/concurrency_in_java_part_1_-_introduction.png\",\"datePublished\":\"2022-06-15T05:27:58+00:00\",\"dateModified\":\"2026-03-11T05:59:41+00:00\",\"description\":\"Read the first part of our blog series devoted to concurrency in Java.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/concurrency-in-java-part-1-introduction\\\/#breadcrumb\"},\"inLanguage\":\"fi\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/thecodest.co\\\/blog\\\/concurrency-in-java-part-1-introduction\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"fi\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/concurrency-in-java-part-1-introduction\\\/#primaryimage\",\"url\":\"https:\\\/\\\/thecodest.co\\\/app\\\/uploads\\\/2024\\\/05\\\/concurrency_in_java_part_1_-_introduction.png\",\"contentUrl\":\"https:\\\/\\\/thecodest.co\\\/app\\\/uploads\\\/2024\\\/05\\\/concurrency_in_java_part_1_-_introduction.png\",\"width\":960,\"height\":540},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/concurrency-in-java-part-1-introduction\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/thecodest.co\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Concurrency in Java Part 1 &#8211; Introduction\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/#website\",\"url\":\"https:\\\/\\\/thecodest.co\\\/\",\"name\":\"The Codest\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/thecodest.co\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"fi\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/#organization\",\"name\":\"The Codest\",\"url\":\"https:\\\/\\\/thecodest.co\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fi\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/thecodest.co\\\/app\\\/uploads\\\/2024\\\/03\\\/thecodest-logo.svg\",\"contentUrl\":\"https:\\\/\\\/thecodest.co\\\/app\\\/uploads\\\/2024\\\/03\\\/thecodest-logo.svg\",\"width\":144,\"height\":36,\"caption\":\"The Codest\"},\"image\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/pl.linkedin.com\\\/company\\\/codest\",\"https:\\\/\\\/clutch.co\\\/profile\\\/codest\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/#\\\/schema\\\/person\\\/7e3fe41dfa4f4e41a7baad4c6e0d4f76\",\"name\":\"thecodest\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fi\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5dbfe6a1e8c86e432e8812759e34e6fe82ebac75119ae3237a6c1311fa19caf4?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5dbfe6a1e8c86e432e8812759e34e6fe82ebac75119ae3237a6c1311fa19caf4?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5dbfe6a1e8c86e432e8812759e34e6fe82ebac75119ae3237a6c1311fa19caf4?s=96&d=mm&r=g\",\"caption\":\"thecodest\"},\"url\":\"https:\\\/\\\/thecodest.co\\\/fi\\\/author\\\/thecodest\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Rinnakkaisuus Javassa Osa 1 - Johdanto - The Codest","description":"Lue ensimm\u00e4inen osa blogisarjastamme, joka on omistettu rinnakkaisuudelle Javassa.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/thecodest.co\/fi\/blogi\/samanaikaisuus-java-osa-1-johdanto\/","og_locale":"fi_FI","og_type":"article","og_title":"Concurrency in Java Part 1 - Introduction","og_description":"Read the first part of our blog series devoted to concurrency in Java.","og_url":"https:\/\/thecodest.co\/fi\/blogi\/samanaikaisuus-java-osa-1-johdanto\/","og_site_name":"The Codest","article_published_time":"2022-06-15T05:27:58+00:00","article_modified_time":"2026-03-11T05:59:41+00:00","og_image":[{"width":960,"height":540,"url":"https:\/\/thecodest.co\/app\/uploads\/2024\/05\/concurrency_in_java_part_1_-_introduction.png","type":"image\/png"}],"author":"thecodest","twitter_card":"summary_large_image","twitter_misc":{"Written by":"thecodest","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/thecodest.co\/blog\/concurrency-in-java-part-1-introduction\/#article","isPartOf":{"@id":"https:\/\/thecodest.co\/blog\/concurrency-in-java-part-1-introduction\/"},"author":{"name":"thecodest","@id":"https:\/\/thecodest.co\/#\/schema\/person\/7e3fe41dfa4f4e41a7baad4c6e0d4f76"},"headline":"Concurrency in Java Part 1 &#8211; Introduction","datePublished":"2022-06-15T05:27:58+00:00","dateModified":"2026-03-11T05:59:41+00:00","mainEntityOfPage":{"@id":"https:\/\/thecodest.co\/blog\/concurrency-in-java-part-1-introduction\/"},"wordCount":1295,"commentCount":0,"publisher":{"@id":"https:\/\/thecodest.co\/#organization"},"image":{"@id":"https:\/\/thecodest.co\/blog\/concurrency-in-java-part-1-introduction\/#primaryimage"},"thumbnailUrl":"https:\/\/thecodest.co\/app\/uploads\/2024\/05\/concurrency_in_java_part_1_-_introduction.png","articleSection":["Software Development"],"inLanguage":"fi","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/thecodest.co\/blog\/concurrency-in-java-part-1-introduction\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/thecodest.co\/blog\/concurrency-in-java-part-1-introduction\/","url":"https:\/\/thecodest.co\/blog\/concurrency-in-java-part-1-introduction\/","name":"Rinnakkaisuus Javassa Osa 1 - Johdanto - The Codest","isPartOf":{"@id":"https:\/\/thecodest.co\/#website"},"primaryImageOfPage":{"@id":"https:\/\/thecodest.co\/blog\/concurrency-in-java-part-1-introduction\/#primaryimage"},"image":{"@id":"https:\/\/thecodest.co\/blog\/concurrency-in-java-part-1-introduction\/#primaryimage"},"thumbnailUrl":"https:\/\/thecodest.co\/app\/uploads\/2024\/05\/concurrency_in_java_part_1_-_introduction.png","datePublished":"2022-06-15T05:27:58+00:00","dateModified":"2026-03-11T05:59:41+00:00","description":"Lue ensimm\u00e4inen osa blogisarjastamme, joka on omistettu rinnakkaisuudelle Javassa.","breadcrumb":{"@id":"https:\/\/thecodest.co\/blog\/concurrency-in-java-part-1-introduction\/#breadcrumb"},"inLanguage":"fi","potentialAction":[{"@type":"ReadAction","target":["https:\/\/thecodest.co\/blog\/concurrency-in-java-part-1-introduction\/"]}]},{"@type":"ImageObject","inLanguage":"fi","@id":"https:\/\/thecodest.co\/blog\/concurrency-in-java-part-1-introduction\/#primaryimage","url":"https:\/\/thecodest.co\/app\/uploads\/2024\/05\/concurrency_in_java_part_1_-_introduction.png","contentUrl":"https:\/\/thecodest.co\/app\/uploads\/2024\/05\/concurrency_in_java_part_1_-_introduction.png","width":960,"height":540},{"@type":"BreadcrumbList","@id":"https:\/\/thecodest.co\/blog\/concurrency-in-java-part-1-introduction\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/thecodest.co\/"},{"@type":"ListItem","position":2,"name":"Concurrency in Java Part 1 &#8211; Introduction"}]},{"@type":"WebSite","@id":"https:\/\/thecodest.co\/#website","url":"https:\/\/thecodest.co\/","name":"Codest","description":"","publisher":{"@id":"https:\/\/thecodest.co\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/thecodest.co\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"fi"},{"@type":"Organization","@id":"https:\/\/thecodest.co\/#organization","name":"Codest","url":"https:\/\/thecodest.co\/","logo":{"@type":"ImageObject","inLanguage":"fi","@id":"https:\/\/thecodest.co\/#\/schema\/logo\/image\/","url":"https:\/\/thecodest.co\/app\/uploads\/2024\/03\/thecodest-logo.svg","contentUrl":"https:\/\/thecodest.co\/app\/uploads\/2024\/03\/thecodest-logo.svg","width":144,"height":36,"caption":"The Codest"},"image":{"@id":"https:\/\/thecodest.co\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/pl.linkedin.com\/company\/codest","https:\/\/clutch.co\/profile\/codest"]},{"@type":"Person","@id":"https:\/\/thecodest.co\/#\/schema\/person\/7e3fe41dfa4f4e41a7baad4c6e0d4f76","name":"thecodest","image":{"@type":"ImageObject","inLanguage":"fi","@id":"https:\/\/secure.gravatar.com\/avatar\/5dbfe6a1e8c86e432e8812759e34e6fe82ebac75119ae3237a6c1311fa19caf4?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/5dbfe6a1e8c86e432e8812759e34e6fe82ebac75119ae3237a6c1311fa19caf4?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/5dbfe6a1e8c86e432e8812759e34e6fe82ebac75119ae3237a6c1311fa19caf4?s=96&d=mm&r=g","caption":"thecodest"},"url":"https:\/\/thecodest.co\/fi\/author\/thecodest\/"}]}},"_links":{"self":[{"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/posts\/3138","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/comments?post=3138"}],"version-history":[{"count":8,"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/posts\/3138\/revisions"}],"predecessor-version":[{"id":8551,"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/posts\/3138\/revisions\/8551"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/media\/3139"}],"wp:attachment":[{"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/media?parent=3138"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/categories?post=3138"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/tags?post=3138"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}