LinkedBlockingQueue vs ConcurrentLinkedQueue

1. Bemutatkozás

LinkedBlockingQueue és ConcurrentLinkedQueue a két leggyakrabban használt egyidejű sor a Java-ban. Bár mindkét várólistát gyakran használják egyidejű adatstruktúraként, finom jellemzők és viselkedési különbségek vannak közöttük.

Ebben a rövid oktatóanyagban megvitatjuk mindkét sort, és elmagyarázzuk azok hasonlóságait és különbségeit.

2. LinkedBlockingQueue

A LinkedBlockingQueue egy opcionálisan korlátozott a sor megvalósításának blokkolása, vagyis szükség esetén megadható a sor mérete.

Hozzunk létre egy LinkedBlockingQueue amely legfeljebb 100 elemet tartalmazhat:

BlockingQueue boundedQueue = új LinkedBlockingQueue (100);

Korlátlanat is létrehozhatunk LinkedBlockingQueue csak nem adja meg a méretet:

BlockingQueue unoundedQueue = new LinkedBlockingQueue ();

A korlátlan sor azt jelenti, hogy a sor méretét a létrehozás során nem adják meg. Ezért a sor dinamikusan növekedhet, amikor elemeket adunk hozzá. Ha azonban nem marad memória, akkor a sor a-t dobja java.lang.OutOfMemoryError.

Hozhatunk létre a LinkedBlockingQueue egy meglévő gyűjteményből is:

Gyűjtemény listOfNumbers = Tömbök.asList (1,2,3,4,5); BlockingQueue queue = új LinkedBlockingQueue (listOfNumbers);

A LinkedBlockingQueue osztály végrehajtja a BlockingQueue interfész, amely a blokkoló jelleget biztosítja számára.

A blokkoló várakozási sor azt jelzi, hogy a sor blokkolja a hozzáférő szálat, ha az megtelt (amikor a sort korlátozza), vagy üres lesz. Ha a sor megtelt, akkor egy új elem hozzáadása blokkolja a hozzáférési szálat, hacsak nincs szabad hely az új elem számára. Hasonlóképpen, ha a sor üres, akkor egy elem elérése blokkolja a hívó szálat:

ExecutorService végrehajtóService = Executors.newFixedThreadPool (1); LinkedBlockingQueue queue = új LinkedBlockingQueue (); executorService.submit (() -> {try {queue.take ();} catch (InterruptedException e) {// kivételkezelés}});

A fenti kódrészletben egy üres sorba lépünk. Ezért a vesz metódus blokkolja a hívó szálat.

A. Blokkoló funkciója LinkedBlockingQueue valamilyen költséggel jár. Ez a költség azért van, mert minden tedd vagy a vesz a művelet a gyártói vagy a fogyasztói szálak között zárolt. Ezért a sok termelővel és fogyasztóval tedd és a cselekvés lassabb lehet.

3. ConcurrentLinkedQueue

A ConcurrentLinkedQueuekorlátlan, szálbiztos és nem blokkoló sor.

Hozzunk létre egy üreset ConcurrentLinkedQueue:

ConcurrentLinkedQueue queue = új ConcurrentLinkedQueue ();

Hozhatunk létre a ConcurrentLinkedQueue egy meglévő gyűjteményből is:

Gyűjtemény listOfNumbers = Tömbök.asList (1,2,3,4,5); ConcurrentLinkedQueue queue = új ConcurrentLinkedQueue (listOfNumbers);

Ellentétben a LinkedBlockingQueue,a ConcurrentLinkedQueue nem blokkoló sor. Így nem blokkol egy szálat, ha a sor üres. Ehelyett visszatér nulla. Mivel nincs korlátozva, a-t dobja java.lang.OutOfMemoryError ha nincs extra memória új elemek hozzáadásához.

Amellett, hogy nem blokkoló, a ConcurrentLinkedQueue további funkcionalitással rendelkezik.

Bármely termelő-fogyasztó forgatókönyv esetén a fogyasztók nem elégednek meg a termelőkkel; azonban több gyártó verseng egymással:

int elem = 1; ExecutorService végrehajtóService = Executors.newFixedThreadPool (2); ConcurrentLinkedQueue queue = új ConcurrentLinkedQueue (); Futható ajánlatTask = () -> queue.offer (elem); Hívható pollTask ​​= () -> {while (queue.peek ()! = Null) {return queue.poll (). IntValue (); } return null; }; executorService.submit (offerTask); Future ReturnElement = végrehajtóSzolgáltatás.submit (pollTask); assertThat (returnElement.get (). intValue (), is (equalTo (elem))); 

Az első feladat, offerTask, hozzáad egy elemet a sorhoz, és a második feladatot, pollTask, szerezzen be egy elemet a sorból. A közvélemény-kutatás feladata először ellenőrzi egy elem várakozási sorát ConcurrentLinkedQueue nem blokkoló és visszatérhet a nulla érték.

4. Hasonlóságok

Mindkét LinkedBlockingQueue és a ConcurrentLinkedQueue várakozási sor megvalósítások és közös jellemzőkkel rendelkeznek. Beszéljük meg a két sor hasonlóságát:

  1. Mindkét végrehajtja a Sor Felület
  2. Mindketten összekapcsolt csomópontokat használjon hogy tárolják elemeiket
  3. Mindkét alkalmasak egyidejű hozzáférési forgatókönyvekre

5. Különbségek

Bár mindkét várólista bizonyos hasonlóságokkal rendelkezik, lényeges jellemzőkbeli különbségek is vannak:

FunkcióLinkedBlockingQueueConcurrentLinkedQueue
A természet blokkolásaEz egy blokkoló sor, és végrehajtja a BlockingQueue felületEz nem blokkoló sor, és nem hajtja végre a BlockingQueue felület
Sor méreteEz opcionálisan korlátozott sor, ami azt jelenti, hogy vannak rendelkezések a sor méretének meghatározására a létrehozás soránKorlátlan sor, és a létrehozás során nincs megadva a sor méretének meghatározása
A természet zárolásaEz zár-alapú sorEz zár nélküli sor
AlgoritmusMegvalósítja reteszelése alapján kétzáras sor algoritmusTámaszkodik a Michael & Scott algoritmus nem blokkoló, zár nélküli sorokhoz
VégrehajtásBan,-ben kétzáras sor algoritmus mechanizmusa, LinkedBlockingQueue két különböző zárat használ - a putLock és a takeLock . A put / take műveletek az első zár típust használja, és a take / poll műveletek a másik zár típust használják CAS-t használ (összehasonlítás és csere) működéséhez
Viselkedés blokkolásaEz egy blokkoló sor. Tehát blokkolja a hozzáférő szálakat, ha a sor üresNem blokkolja a hozzáférő szálat, ha a sor üres és visszatér nulla

6. Következtetés

Ebben a cikkben megtudtuk LinkedBlockingQueue és ConcurrentLinkedQueue.

Először külön megvitattuk ezt a két várólista megvalósítást és néhány jellemzőjüket. Aztán megláttuk a hasonlóságokat e két sor megvalósítás között. Végül feltártuk a különbségeket e két sormegvalósítás között.

Mint mindig, a példák forráskódja elérhető a GitHubon.


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