Ikke-blokkerende køer
![](https://cdn.codegym.cc/images/article/128e424c-63bb-47db-9d23-7ce3ae97fa4a/512.jpeg)
Trådsikre og viktigst av alt ikke-blokkerende køimplementeringer på koblede noder.
ConcurrentLinkedQueue<E> - den bruker en ventefri algoritme tilpasset for å jobbe med søppelsamleren. Denne algoritmen er ganske effektiv og veldig rask, siden den er bygget på CAS. Size()- metodenkan kjøre i lang tid, så det er best å ikke trekke den hele tiden.
ConcurrentLinkedDeque<E> - Deque står for Double ended queue. Dette betyr at data kan legges til og trekkes fra begge sider. Følgelig støtter klassen begge driftsmodusene: FIFO (First In First Out) og LIFO (Last In First Out).
I praksis bør ConcurrentLinkedDeque brukes hvis LIFO er absolutt nødvendig, siden på grunn av toveisiteten til nodene, taper denne klassen halvparten i ytelse sammenlignet med ConcurrentLinkedQueue .
import java.util.concurrent.ConcurrentLinkedQueue;
public class ConcurrentLinkedQueueExample {
public static void main(String[] args) {
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
Thread producer = new Thread(new Producer(queue));
Thread consumer = new Thread(new Consumer(queue));
producer.start();
consumer.start();
}
}
class Producer implements Runnable {
ConcurrentLinkedQueue<String> queue;
Producer(ConcurrentLinkedQueue<String> queue){
this.queue = queue;
}
public void run() {
System.out.println("Class for adding items to the queue");
try {
for (int i = 1; i < 5; i++) {
queue.add("Item #" + i);
System.out.println("Added: Item #" + i);
Thread.sleep(300);
}
} catch (InterruptedException ex) {
ex.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
class Consumer implements Runnable {
ConcurrentLinkedQueue<String> queue;
Consumer(ConcurrentLinkedQueue<String> queue){
this.queue = queue;
}
public void run() {
String str;
System.out.println("Class for getting items from the queue");
for (int x = 0; x < 5; x++) {
while ((str = queue.poll()) != null) {
System.out.println("Pulled out: " + str);
}
try {
Thread.sleep(600);
} catch (InterruptedException ex) {
ex.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
}
Blokkering av køer
![](https://cdn.codegym.cc/images/article/8c8152d6-ffe6-4165-879c-3bcae893696f/1080.jpeg)
BlockingQueue<E> -grensesnitt - hvis det er mye data, er ikke ConcurrentLinkedQueue nok.
Når tråder ikke klarer jobben sin, kan du enkelt få en OutOfMemmoryException . Og for at slike tilfeller ikke skal oppstå, har vi en BlockingQueue for arbeid med tilstedeværelsen av forskjellige metoder for å fylle og jobbe med køen og betingede låser.
BlockingQueue gjenkjenner ikke null-elementer og kaster et NullPointerException når du prøver å legge til eller hente et slikt element. Avstemningsmetoden returnerer et null-element hvis intet element har blitt plassert i køen innen tidsavbruddet.
BlockingQueue<E>-implementeringer
La oss ta en nærmere titt på hver av våre BlockingQueue- implementeringer :
ArrayBlockingQueue<E> er en blokkerende køklasse bygget på den klassiske ringbufferen. Her har vi muligheten til å håndtere "ærligheten" til låser. Hvis fair=false (standard), er ikke trådbestilling garantert.
DelayQueue<E extends Delayed> er en klasse som lar deg trekke elementer fra køen bare etter en viss forsinkelse, definert i hvert element gjennom getDelay- metoden til Delayed - grensesnittet.
LinkedBlockingQueue<E> er en blokkeringskø på koblede noder, implementert på "to-låskø"-algoritmen: den første låsen er for å legge til, den andre er for å trekke et element fra køen. På grunn av låser, sammenlignet med ArrayBlockingQueue , har denne klassen høy ytelse, men den krever mer minne. Køstørrelsen angis via konstruktøren og er lik Integer.MAX_VALUE som standard.
PriorityBlockingQueue<E> er en flertråds wrapper over PriorityQueue . Komparatoren er ansvarlig for logikken som elementet vil bli lagt til. Det minste elementet kommer først ut.
SynchronousQueue<E> - køen fungerer etter FIFO (først-inn-først-ut)-prinsippet. Hver innsettingsoperasjon blokkerer "Produsent"-tråden til "Forbruker"-tråden trekker elementet fra køen og omvendt, "Forbruker" vil vente til "Produsent" setter inn elementet.
BlockingDeque<E> er et grensesnitt som beskriver tilleggsmetoder for en toveis blokkeringskø. Data kan settes inn og trekkes ut fra begge sider av køen.
LinkedBlockingDeque<E> er en toveis blokkeringskø på koblede noder, implementert som en enkel toveis liste med én lås. Køstørrelsen angis via konstruktøren og er lik Integer.MAX_VALUE som standard.
TransferQueue<E> - grensesnittet er interessant ved at når et element legges til køen, er det mulig å blokkere den innsatte Produsent- tråden til en annen Consumer- tråd trekker elementet fra køen. Du kan også legge til en sjekk for et bestemt tidsavbrudd eller sette en sjekk for ventende forbrukere . Som et resultat får vi en dataoverføringsmekanisme med støtte for asynkrone og synkrone meldinger.
LinkedTransferQueue<E> er en implementering av TransferQueue basert på Dual Queue with Slack-algoritmen. Bruker mye CAS (se over) og gjengeparkering når den ikke er i bruk.