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:
- Mindkét végrehajtja a Sor Felület
- Mindketten összekapcsolt csomópontokat használjon hogy tárolják elemeiket
- 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ó | LinkedBlockingQueue | ConcurrentLinkedQueue |
---|---|---|
A természet blokkolása | Ez egy blokkoló sor, és végrehajtja a BlockingQueue felület | Ez nem blokkoló sor, és nem hajtja végre a BlockingQueue felület |
Sor mérete | Ez 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án | Korlátlan sor, és a létrehozás során nincs megadva a sor méretének meghatározása |
A természet zárolása | Ez zár-alapú sor | Ez zár nélküli sor |
Algoritmus | Megvalósítja reteszelése alapján kétzáras sor algoritmus | Támaszkodik a Michael & Scott algoritmus nem blokkoló, zár nélküli sorokhoz |
Végrehajtás | Ban,-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ása | Ez egy blokkoló sor. Tehát blokkolja a hozzáférő szálakat, ha a sor üres | Nem 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.