Java CyclicBarrier vs CountDownLatch

1. Bemutatkozás

Ebben az oktatóanyagban összehasonlítjuk Ciklikus akadály és CountDownLatch és próbáld megérteni a kettő közötti hasonlóságokat és különbségeket.

2. Mik ezek?

Ha a párhuzamosságról van szó, nehéz lehet megfogalmazni, hogy mindegyik mit kíván megvalósítani.

Első és legfontosabb mindkettő CountDownLatch és Ciklikus akadály többszálas alkalmazások kezelésére szolgálnak.

És, mindkettő azt hivatott kifejezni, hogy az adott szál vagy szálcsoport miként várjon.

2.1. CountDownLatch

A CountDownLatch olyan konstrukció, amely egy szál várjons közben más szálak visszaszámol addig, amíg el nem éri a nullát.

Ezt úgy gondolhatjuk, mint egy készülő étterem étele. Nem számít, melyik szakács készíti elő a sok n tárgyakat, a pincérnek kell várjon amíg az összes elem a tányéron van. Ha egy lemez vesz n tételek, bármilyen szakács visszaszámol a tányérra helyezett minden cikk reteszén.

2.2. Ciklikus akadály

A Ciklikus akadály egy újrafelhasználható konstrukció, ahol egy szálcsoport van vár együtt, amíg az összes szál megérkezik. Ekkor a sorompó megtörik és egy akció választható.

Úgy gondolhatunk erre, mint egy baráti társaságra. Minden alkalommal, amikor éttermet terveznek enni, eldöntenek egy közös pontot, ahol találkozhatnak. Ők várjon egymásnak ott, és csak akkor, amikor mindenki megérkezik mehetnek-e az étterembe együtt enni.

2.3. További irodalom

És ezekről külön-külön sokkal részletesebben olvassa el korábbi oktatóanyagainkat CountDownLatch és Ciklikus akadály illetőleg.

3. Feladatok és szálak

Vessünk egy mélyebb elmélyülést e két osztály szemantikai különbségeibe.

Amint azt a meghatározások Ciklikus akadály lehetővé teszi, hogy számos szál várjon egymásra, míg CountDownLatch lehetővé teszi egy vagy több szál megvárását, amíg számos feladat befejeződik.

Röviden, Ciklikus akadály számláját tartja fenn szálak mivel CountDownLatch számláját tartja fenn feladatok.

A következő kódban meghatározzuk a CountDownLatch kettővel számolva. Ezután felhívjuk visszaszámlálás() kétszer egyetlen szálból:

CountDownLatch countDownLatch = new CountDownLatch (2); Téma t = új Téma (() -> {countDownLatch.countDown (); countDownLatch.countDown ();}); t.start (); countDownLatch.await (); assertEquals (0, countDownLatch.getCount ());

Amint a retesz eléri a nullát, a hívás várják visszatér.

Vegye figyelembe, hogy ebben az esetben kétszer csökkenthetjük ugyanezt a szálat.

CyclicBarrier, bár ebben a kérdésben más.

A fenti példához hasonlóan létrehozunk egy CyclicBarrier, ismét kettő számlálásával és hívjon várják() rajta, ezúttal ugyanabból a szálból:

CyclicBarrier cyclicBarrier = új CyclicBarrier (2); Téma t = új Téma (() -> {próbáld ki {cyclicBarrier.await (); cyclicBarrier.await ();} catch (InterruptedException | BrokenBarrierException e) {// hibakezelés}}); t.start (); assertEquals (1, cyclicBarrier.getNumberWaiting ()); assertFalse (cyclicBarrier.isBroken ());

Az első különbség itt az, hogy a várakozó szálak önmagukban is akadályt jelentenek.

Másodszor, és ami még fontosabb: a második várják() haszontalan. Egyetlen szál sem visszaszámol kétszer egy akadályt.

Valóban, mert t kell várjon hogy egy másik szál hívjon várják() - hogy a gróf kettőre kerüljön - tMásodik hívása várják() valójában addig nem hivatkoznak rá, amíg a sorompó már nem szakadt meg!

Tesztünk során a korlátot nem lépték át, mert csak egy szál várt ránk, és nem az a két szál, amelyre szükség lenne az akadály lezárásához. Ez nyilvánvaló a cyclicBarrier.isBroken () metódus, amely visszatér hamis.

4. Újrafelhasználhatóság

A második legnyilvánvalóbb különbség e két osztály között az újrafelhasználhatóság. Bővebben, amikor a sorompó beér Ciklikus akadály, a számláló visszaáll az eredeti értékére.CountDownLatch más, mert a gróf soha nem áll vissza.

Az adott kódban meghatározzuk a CountDownLatch a 7. számmal és 20 különböző híváson keresztül számlálja:

CountDownLatch countDownLatch = new CountDownLatch (7); ExecutorService es = Executors.newFixedThreadPool (20); for (int i = 0; i {long prevValue = countDownLatch.getCount (); countDownLatch.countDown (); if (countDownLatch.getCount ()! = prevValue) {outputScraper.add ("Count Count");}}); } es.kapcsolás (); assertTrue (outputScraper.size () <= 7);

Megfigyeljük, hogy annak ellenére, hogy 20 különböző szál hív visszaszámlálás(), a számlálás nem áll vissza, ha eléri a nullát.

A fenti példához hasonlóan definiáljuk a Ciklikus akadály a 7. számmal és várjon rá 20 különböző szálból:

CyclicBarrier cyclicBarrier = új CyclicBarrier (7); ExecutorService es = Executors.newFixedThreadPool (20); for (int i = 0; i {try {if (cyclicBarrier.getNumberWaiting () 7);

Ebben az esetben megfigyeljük, hogy az érték minden új szál futtatásakor csökken, ha visszaáll az eredeti értékre, amint eléri a nullát.

5. Következtetés

Összességében, Ciklikus akadály és CountDownLatchmindkettő hasznos eszköz a szálak közötti szinkronizáláshoz. Az általuk nyújtott funkcionalitás szempontjából azonban alapvetően különböznek egymástól. Fontolja meg alaposan mindegyiket, amikor meghatározza, hogy melyik a megfelelő a munkához.

Szokás szerint az összes megvitatott példa a Githubon érhető el.