Útmutató a Java egyidejű várólistáihoz

1. Áttekintés

Ebben az oktatóanyagban áttekintjük a Java egyidejű sorainak néhány fő megvalósítását. A várólisták általános bemutatásához olvassa el a Java útmutatónkat Sor Interfész cikk.

2. Sorok

Többszálas alkalmazásokban a soroknak több egyidejű termelő-fogyasztó forgatókönyvet kell kezelniük. Az egyidejű sor helyes megválasztása kulcsfontosságú lehet az algoritmusaink jó teljesítményének eléréséhez.

Először néhány fontos különbséget fogunk látni a blokkoló és a nem blokkoló sor között. Ezután megnézünk néhány megvalósítást és bevált gyakorlatot.

2. Blokkolás vs nem blokkoló várólista

BlockingQueue ajánlatok egyszerű menetbiztos mechanizmus. Ebben a sorban a szálaknak meg kell várniuk a sor elérhetőségét. A gyártók megvárják a rendelkezésre álló kapacitást az elemek hozzáadása előtt, míg a fogyasztók addig várnak, amíg a sor üres lesz. Ezekben az esetekben a nem blokkoló sor kivételt dob, vagy speciális értéket ad vissza, például nulla vagy hamis.

Ennek a blokkoló mechanizmusnak az elérése érdekében a BlockingQueue interfész két funkciót tesz ki a normál tetején Sor funkciók: tedd és vesz. Ezek a funkciók megegyeznek a hozzá és eltávolítani szabványban Sor.

3. Egyidejű Sor Végrehajtások

3.1. ArrayBlockingQueue

Ahogy a neve is mutatja, ez a sor egy tömböt használ belsőleg. Ennek következtében az korlátozott várólista, vagyis rögzített méretű.

Az egyszerű munkasor egy felhasználási eset. Ez a forgatókönyv gyakran alacsony termelő-fogyasztó arányt jelent, ahol az időigényes feladatokat több munkavállaló között osztjuk szét. Mivel ez a sor nem növekedhet a végtelenségig, a méretkorlát biztonsági küszöbként működik, ha a memória kérdés.

A memóriáról szólva fontos megjegyezni, hogy a sor előre lefoglalja a tömböt. Bár ez javíthatja az áteresztőképességet, mégis a szükségesnél is több memóriát fogyaszthat. Például egy nagy kapacitású sor hosszú ideig üres maradhat.

Továbbá a ArrayBlockingQueue egyetlen zárat használ mindkettőhöz tedd és vesz tevékenységek. Ez biztosítja, hogy a bejegyzések ne kerüljenek felülírásra, teljesítmény-találat árán.

3.2. LinkedBlockingQueue

A LinkedBlockingQueue használja a LinkedList változat, ahol minden egyes sorelem egy új csomópont. Bár ez elvileg korlátlaná teszi a várólistát, mégis kemény határértéke van Egész.MAX_VALUE.

Másrészt a konstruktor segítségével beállíthatjuk a sor méretét LinkedBlockingQueue (int kapacitás).

Ez a sor különálló zárakat használ a tedd és vesz tevékenységek. Ennek eredményeként mindkét művelet párhuzamosan végezhető és javítja az átvitelt.

Mivel a LinkedBlockingQueue korlátozott vagy korlátlan lehet, miért használnánk a ArrayBlockingQueue ezen túl? LinkedBlockingQueue el kell osztania és el kell osztania a csomópontokat minden alkalommal, amikor egy elemet hozzáadnak vagy eltávolítanak a sorból. Emiatt egy ArrayBlockingQueue jobb alternatíva lehet, ha a sor gyorsan növekszik és gyorsan zsugorodik.

Az előadás LinkedBlockingQueue kiszámíthatatlannak mondják. Más szavakkal, mindig át kell alakítanunk a forgatókönyveinket, hogy a megfelelő adatszerkezetet használjuk.

3.3. PriorityBlockingQueue

A PriorityBlockingQueue a mi megoldásunk amikor meghatározott sorrendben kell fogyasztanunk a tételeket. Ennek elérése érdekében a PriorityBlockingQueue tömb alapú bináris kupacot használ.

Míg belsőleg egyetlen zárszerkezetet használ, a vesz művelet egyidejűleg történhet a tedd művelet. Egy egyszerű spinlock használata ezt lehetővé teszi.

Tipikus felhasználási eset a különböző prioritású feladatok fogyasztása. Nem akarjuk, hogy egy alacsony prioritású feladat lépjen a kiemelt feladat helyébe.

3.4. DelayQueue

Használjuk a DelayQueueamikor a fogyasztó csak lejárt tárgyat vehet fel. Érdekes módon a PriorityQueue belsőleg rendelje meg az elemeket a lejáratukig.

Mivel ez nem általános célú sor, nem terjed ki annyi forgatókönyvre, mint a ArrayBlockingQueue vagy a LinkedBlockingQueue. Például ezt a sort használhatjuk a NodeJS-ben találhatóhoz hasonló egyszerű eseményhurok megvalósítására. Aszinkron feladatokat a sorba helyezzük későbbi feldolgozás céljából, amikor azok lejárnak.

3.5. LinkedTransferQueue

A LinkedTransferQueue bevezeti a átruházás módszer. Míg más sorok általában blokkolják az elemek előállításakor vagy fogyasztásakor, az LinkedTransferQueuelehetővé teszi a termelő számára, hogy megvárja a termék fogyasztását.

Használjuk a LinkedTransferQueue amikor garanciára van szükségünk arról, hogy egy adott elemet, amelyet a sorba tettünk, valaki elvette. Ezen sor segítségével egy egyszerű ellennyomás algoritmust is megvalósíthatunk. Valójában a gyártók fogyasztásig történő blokkolásával a fogyasztók irányíthatják az előállított üzenetek áramlását.

3.6. SynchronousQueue

Míg a várólisták általában sok elemet tartalmaznak, a SynchronousQueue mindig legfeljebb egyetlen elem lesz. Más szóval látnunk kell a SynchronousQueue mint egy egyszerű módja az adatok két szál közötti cseréjének.

Ha két olyan szálunk van, amelyekhez hozzáférés szükséges egy megosztott állapothoz, ezeket gyakran szinkronizáljuk CountDownLatch vagy más szinkronizációs mechanizmusok. Az a használatával SynchronousQueue, tudunk kerülje a szálak kézi szinkronizálását.

3.7. ConcurrentLinkedQueue

A ConcurrentLinkedQueue az egyetlen nem blokkoló sor ebben az útmutatóban. Következésképpen „várakozás nélküli” algoritmust biztosít, ahol hozzá és közvélemény kutatás garantáltan menetbiztosak és azonnal visszaküldhetők. A zárak helyett ez a sor CAS-t (összehasonlítás-csere) használ.

Belsőleg a (z) algoritmusán alapul Egyszerű, gyors és praktikus nem blokkoló és blokkoló párhuzamos várólista algoritmusok Maged M. Michael és Michael L. Scott.

Ez egy tökéletes jelölt a modern reaktív rendszerek számára, ahol a blokkoló adatszerkezetek használata gyakran tilos.

Másrészt, ha a fogyasztónk egy hurkon várakozik, valószínűleg jobb alternatívaként a blokkolási sort kell választanunk.

4. Következtetés

Ebben az útmutatóban végigjártuk a párhuzamos soros megvalósításokat, megvitatva azok erősségeit és gyengeségeit. Ezt szem előtt tartva jobban felkészültek vagyunk a hatékony, tartós és elérhető rendszerek kifejlesztésére.


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