Java CyclicBarrier vs CountDownLatch

1. Introduktion

I denne vejledning sammenligner vi Cyklisk barriere og CountDownLatch og prøv at forstå ligheder og forskelle mellem de to.

2. Hvad er disse?

Når det kommer til samtidighed, kan det være udfordrende at konceptualisere, hvad hver enkelt er beregnet til at opnå.

Først og fremmest begge dele CountDownLatch og Cyklisk barriere bruges til styring af applikationer med flere tråde.

Og, de er begge beregnet til at udtrykke, hvordan en given tråd eller gruppe af tråde skal vente.

2.1. CountDownLatch

EN CountDownLatch er en konstruktion, der er en tråd ventes på, mens andre tråde tælle ned på låsen, indtil den når nul.

Vi kan tænke på dette som en skål på en restaurant, der er under forberedelse. Uanset hvilken kok der forbereder dog mange af n varer skal tjeneren vente indtil alle genstande er på pladen. Hvis en plade tager n ting, enhver kok vil tælle ned på låsen for hvert emne, hun lægger på pladen.

2.2. Cyklisk barriere

EN Cyklisk barriere er en genanvendelig konstruktion, hvor en gruppe tråde venter sammen indtil alle trådene ankomme. På det tidspunkt er barrieren brudt og en handling kan eventuelt tages.

Vi kan tænke på dette som en gruppe venner. Hver gang de planlægger at spise på en restaurant, beslutter de et fælles punkt, hvor de kan mødes. De vente for hinanden der, og kun når alle ankommer kan de gå til restauranten for at spise sammen.

2.3. Yderligere læsning

Og for meget mere detaljeret om hver af disse individuelt, se vores tidligere tutorials om CountDownLatch og Cyklisk barriere henholdsvis.

3. Opgaver vs. tråde

Lad os tage et dybere dykke ned i nogle af de semantiske forskelle mellem disse to klasser.

Som anført i definitionerne, Cyklisk barriere tillader et antal tråde at vente på hinanden, mens CountDownLatch tillader en eller flere tråde at vente på, at et antal opgaver er afsluttet.

Kort sagt, Cyklisk barriere opretholder en optælling af tråde der henviser til CountDownLatch opretholder en optælling af opgaver.

I den følgende kode definerer vi a CountDownLatch med et antal på to. Dernæst kalder vi countDown () to gange fra en enkelt tråd:

CountDownLatch countDownLatch = ny CountDownLatch (2); Tråd t = ny Tråd (() -> {countDownLatch.countDown (); countDownLatch.countDown ();}); t.start (); countDownLatch.await (); assertEquals (0, countDownLatch.getCount ());

Når låsen når nul, kaldes til vente vender tilbage.

Bemærk, at i dette tilfælde vi var i stand til at få den samme tråd til at sænke antallet to gange.

Cyklisk barriere, er dog anderledes på dette punkt.

I lighed med ovenstående eksempel opretter vi en Cyklisk barriere, igen med et antal på to og ring vente() på den, denne gang fra samme tråd:

CyclicBarrier cyclicBarrier = ny CyclicBarrier (2); Tråd t = ny Tråd (() -> {prøv {cyclicBarrier.await (); cyclicBarrier.await ();} fangst (InterruptedException | BrokenBarrierException e) {// fejlhåndtering}}); t.start (); assertEquals (1, cyclicBarrier.getNumberWaiting ()); assertFalse (cyclicBarrier.isBroken ());

Den første forskel her er, at de tråde, der venter, i sig selv er barrieren.

For det andet og vigtigere, Sekundet vente() er ubrugelig. En enkelt tråd kan ikke tælle ned en barriere to gange.

Faktisk fordi t skal vente for en anden tråd at ringe til vente() - for at bringe optællingen til to - t'S andet opkald til vente() vil ikke blive påberåbt, før barrieren allerede er brudt!

I vores test barrieren er ikke blevet krydset, fordi vi kun har en tråd, der venter, og ikke de to tråde, der kræves for at barrieren skal udløses. Dette fremgår også af cyclicBarrier.isBroken () metode, som vender tilbage falsk.

4. Genanvendelighed

Den næst mest tydelige forskel mellem disse to klasser er genanvendelighed. At uddybe, når barrieren kører ind Cyklisk barriere, nulstilles antallet til dets oprindelige værdi.CountDownLatch er anderledes, fordi optællingen aldrig nulstilles.

I den givne kode definerer vi a CountDownLatch med tæller 7 og tæl det gennem 20 forskellige opkald:

CountDownLatch countDownLatch = ny CountDownLatch (7); ExecutorService es = Executors.newFixedThreadPool (20); for (int i = 0; i {lang prevValue = countDownLatch.getCount (); countDownLatch.countDown (); hvis (countDownLatch.getCount ()! = prevValue) {outputScraper.add ("Antal opdateret");}}); } es.afbrydelse (); assertTrue (outputScraper.size () <= 7);

Vi bemærker, at selvom 20 forskellige tråde kalder countDown (), nulstilles optællingen ikke, når den når nul.

Svarende til ovenstående eksempel definerer vi a Cyklisk barriere med count 7 og vent på det fra 20 forskellige tråde:

CyclicBarrier cyclicBarrier = ny CyclicBarrier (7); ExecutorService es = Executors.newFixedThreadPool (20); for (int i = 0; jeg {prøv {hvis (cyclicBarrier.getNumberWaiting () 7);

I dette tilfælde bemærker vi, at værdien falder hver gang en ny tråd kører ved at nulstille til den oprindelige værdi, når den når nul.

5. Konklusion

Alt i alt, Cyklisk barriere og CountDownLatcher begge nyttige værktøjer til synkronisering mellem flere tråde. De er dog fundamentalt forskellige med hensyn til den funktionalitet, de leverer. Overvej hver omhyggeligt, når du bestemmer, hvad der er det rigtige for jobbet.

Som sædvanligt kan du få adgang til alle de diskuterede eksempler på Github.


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