LinkedBlockingQueue vs ConcurrentLinkedQueue

1. Uvod

LinkedBlockingQueue i ConcurrentLinkedQueue dva su najčešće korištena istodobna reda u Javi. Iako se oba reda često koriste kao istodobna struktura podataka, među njima postoje suptilne karakteristike i razlike u ponašanju.

U ovom kratkom vodiču razgovarat ćemo o oba ova reda i objasniti njihove sličnosti i razlike.

2. LinkedBlockingQueue

The LinkedBlockingQueue je po želji ograničeno blokiranje implementacije reda, što znači da se veličina reda može odrediti ako je potrebno.

Stvorimo a LinkedBlockingQueue koji može sadržavati do 100 elemenata:

BlockingQueue boundedQueue = novi LinkedBlockingQueue (100);

Također možemo stvoriti neograničeni LinkedBlockingQueue samo ne navodeći veličinu:

BlockingQueue unboundedQueue = novo LinkedBlockingQueue ();

Neograničeni red podrazumijeva da veličina reda nije navedena tijekom izrade. Stoga red može dinamički rasti kako mu se dodaju elementi. Međutim, ako nema više memorije, red čekanja baca znak java.lang.OutOfMemoryError.

Možemo stvoriti LinkedBlockingQueue iz postojeće kolekcije također:

List CollectionOfNumbers = Arrays.asList (1,2,3,4,5); BlockingQueue red = novi LinkedBlockingQueue (listOfNumbers);

The LinkedBlockingQueue razred provodi BlockingQueue sučelje koje mu pruža blokadu.

Red za blokiranje označava da red blokira pristupnu nit ako je puna (kada je red ograničen) ili postane prazna. Ako je red pun, dodavanje novog elementa blokirat će pristupnu nit osim ako za novi element nema prostora. Slično tome, ako je red prazan, pristup elementu blokira pozivajuću nit:

ExecutorService executorService = Izvršitelji.newFixedThreadPool (1); LinkedBlockingQueue red = novi LinkedBlockingQueue (); executorService.submit (() -> {try {queue.take ();} catch (InterruptedException e) {// rukovanje iznimkama}});

U gornjem isječku koda pristupamo praznom redu. Stoga je uzeti metoda blokira pozivajuću nit.

Značajka blokiranja LinkedBlockingQueue je povezan s nekim troškovima. Ovaj je trošak jer svaki staviti ili uzeti operacija je zaključavanje koje se natječe između niti proizvođača ili potrošača. Stoga, u scenarijima s mnogim proizvođačima i potrošačima, staviti a poduzimanje radnji može biti sporije.

3. ConcurrentLinkedQueue

A ConcurrentLinkedQueueje neograničen, bez niti siguran i neblokirajući red.

Stvorimo prazno ConcurrentLinkedQueue:

ConcurrentLinkedQueue red = novi ConcurrentLinkedQueue ();

Možemo stvoriti ConcurrentLinkedQueue iz postojeće kolekcije:

List CollectionOfNumbers = Arrays.asList (1,2,3,4,5); ConcurrentLinkedQueue red = novi ConcurrentLinkedQueue (listOfNumbers);

Za razliku od a LinkedBlockingQueue,a ConcurrentLinkedQueue je neblokirajući red. Dakle, ne blokira nit kada je red prazan. Umjesto toga, vraća se null. Budući da je neograničen, bacit će znak java.lang.OutOfMemoryError ako nema dodatne memorije za dodavanje novih elemenata.

Osim što ne blokira, a ConcurrentLinkedQueue ima dodatnu funkcionalnost.

U bilo kojem scenariju proizvođač-potrošač, potrošači se neće zadovoljiti proizvođačima; međutim, više će se proizvođača međusobno natjecati:

int element = 1; ExecutorService executorService = Izvršitelji.newFixedThreadPool (2); ConcurrentLinkedQueue red = novi ConcurrentLinkedQueue (); Izvodljiva ponudaTask = () -> queue.offer (element); Pozivna pollTask ​​= () -> {while (queue.peek ()! = Null) {return queue.poll (). IntValue (); } return null; }; executorService.submit (offerTask); Budućnost returnElement = executorService.submit (pollTask); assertThat (returnElement.get (). intValue (), je (jednakTo (element))); 

Prvi zadatak, ponudaZadatak, dodaje element u red, a drugi zadatak, PollTask, dohvatiti element iz reda. Zadatak ankete dodatno prvo provjerava u redu za element kao ConcurrentLinkedQueue ne blokira i može vratiti a null vrijednost.

4. Sličnosti

Oba LinkedBlockingQueue i ConcurrentLinkedQueue su primjene u redu i dijele neke zajedničke karakteristike. Razgovarajmo o sličnostima ova dva reda:

  1. Oba provodi Red Sučelje
  2. Oboje koristiti povezane čvorove za pohranu njihovih elemenata
  3. Oba prikladni su za istodobne scenarije pristupa

5. Razlike

Iako oba ova reda imaju određene sličnosti, postoje i značajne razlike u karakteristikama:

ZnačajkaLinkedBlockingQueueConcurrentLinkedQueue
Blokiranje prirodeTo je red za blokiranje i implementira BlockingQueue sučeljeTo je neblokirajući red i ne primjenjuje BlockingQueue sučelje
Veličina redaTo je izborno ograničen red, što znači da postoje odredbe koje definiraju veličinu reda tijekom stvaranjaTo je neograničeni red i ne postoji odredba koja će odrediti veličinu reda tijekom stvaranja
Zaključavanje prirodeto je red zasnovan na zaključavanjuto je red bez zaključavanja
AlgoritamProvodi njegovo zaključavanje na temelju red s dvije brave algoritamOslanja se na Michael & Scott algoritam za neblokirajuće redove bez zaključavanja
ProvedbaU red s dvije brave mehanizam algoritma, LinkedBlockingQueue koristi dvije različite brave - putLock i takeLock . The staviti / uzeti Operacije koristi prvi tip brave, a uzeti / anketirati koristite druge vrste brave Koristi CAS (Usporedite i zamijenite) za svoje poslovanje
Blokiranje ponašanjaTo je red za blokiranje. Dakle, blokira niti za pristup kada je red prazanNe blokira pristupnu nit kada je red prazan i vraća se null

6. Zaključak

U ovom smo članku saznali više o LinkedBlockingQueue i ConcurrentLinkedQueue.

Prvo smo pojedinačno razgovarali o ove dvije implementacije reda i nekim njihovim karakteristikama. Zatim smo vidjeli sličnosti između ove dvije implementacije reda. Konačno, istražili smo razlike između ove dvije implementacije reda.

Kao i uvijek, izvorni kod primjera dostupan je na GitHubu.


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