Jak korzystać z ConcurrentLinkedQueue?

Jak używać ConcurrentLinkedQueue w Javie?
Używając tego LinkedQueue, Czy muszę martwić się o współbieżność w kolejce? Czy po prostu muszę zdefiniować dwie metody (jedną do pobierania elementów z listy, a drugą do dodawania elementów do listy)?
Uwaga: oczywiście te dwie metody muszą być zsynchronizowane. Prawda?


EDIT: próbuję zrobić tak: mam klasę (w Javie) z jedną metodą do pobierania elementów z kolejki i inną klasę z jedną metodą do dodawania elementów do Kolejka Elementy dodane i pobrane z listy są obiektami mojej własnej klasy.

Jeszcze jedno pytanie: Czy muszę to robić w metodzie remove:

while (queue.size() == 0){ 
  wait(); 
  queue.poll();
}
Mam tylko jednego konsumenta i jednego producenta.
Author: P̲̳x͓L̳, 2009-03-05

6 answers

Nie, metody nie muszą być synchronizowane i nie musisz definiować żadnych metod; są one już w ConcurrentLinkedQueue, po prostu ich używaj. ConcurrentLinkedQueue wykonuje wszystkie operacje blokowania i inne operacje, których potrzebujesz wewnętrznie; twój producent(y) dodaje dane do kolejki, a twoi konsumenci szukają ich.

Najpierw Utwórz kolejkę:

Queue<YourObject> queue = new ConcurrentLinkedQueue<YourObject>();

Teraz, gdziekolwiek tworzysz swoje obiekty producenta/konsumenta, przejdź do kolejki, aby mieli gdzie umieścić swoje obiekty (ty do tego przydałby się setter, ale wolę robić tego typu rzeczy w konstruktorze):

YourProducer producer = new YourProducer(queue);

I:

YourConsumer consumer = new YourConsumer(queue);

I dodaj do niego rzeczy w swoim producencie:

queue.offer(myObject);

I wyjmij rzeczy w swoim konsumencie (jeśli kolejka jest pusta, poll() zwróci null, więc sprawdź to):

YourObject myObject = queue.poll();

Aby uzyskać więcej informacji zobacz Javadoc

EDIT:

Jeśli chcesz zablokować oczekiwanie, aby kolejka nie była pusta, prawdopodobnie chcesz użyć LinkedBlockingQueue i użyj metody take (). Jednak LinkedBlockingQueue ma maksymalną pojemność (domyślnie Integer.MAX_VALUE, czyli ponad dwa miliardy), a więc może być, ale nie musi być odpowiednie w zależności od okoliczności.

Jeśli masz tylko jeden wątek umieszczający rzeczy w kolejce, a inny wątek usuwający rzeczy z kolejki, ConcurrentLinkedQueue jest prawdopodobnie przesadą. To bardziej za to, że możesz mieć setki, a nawet tysiące wątków, które mają dostęp do kolejki w w tym samym czasie. Twoje potrzeby prawdopodobnie zostaną zaspokojone za pomocą:

Queue<YourObject> queue = Collections.synchronizedList(new LinkedList<YourObject>());

Plus tego jest to, że blokuje instancję (kolejkę), dzięki czemu można synchronizować kolejkę, aby zapewnić atomiczność operacji złożonych (jak wyjaśnia Jared). Nie można tego zrobić za pomocą ConcurrentLinkedQueue, ponieważ wszystkie operacje są wykonywane bez blokowania instancji (przy użyciu Javy.util./ align = "left" / zmienne atomowe). Nie musisz tego robić, jeśli chcesz zablokować kolejkę, gdy kolejka jest pusta, ponieważ poll() po prostu zwróci null, gdy kolejka jest pusta, a poll () jest atomowa. Sprawdź, czy poll () zwraca null. Jeśli tak, poczekaj (), a następnie spróbuj ponownie. Nie trzeba zamykać.

Wreszcie:

Szczerze mówiąc, użyłbym LinkedBlockingQueue. To nadal przesada dla Twojej aplikacji, ale szanse są, że będzie działać dobrze. Jeśli nie jest wystarczająco wydajny (profil!w przeciwieństwie do innych, nie musisz się zajmować żadnymi zsynchronizowanymi rzeczami: {]}
BlockingQueue<YourObject> queue = new LinkedBlockingQueue<YourObject>();

queue.put(myObject); // Blocks until queue isn't full.

YourObject myObject = queue.take(); // Blocks until queue isn't empty.
Wszystko inne jest takie samo. Put prawdopodobnie nie zablokuje, ponieważ prawdopodobnie nie umieścisz dwóch miliardów obiektów w kolejce.
 139
Author: Adam Jaskiewicz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-16 07:16:01

Jest to w dużej mierze duplikat innego pytania .

Oto część tej odpowiedzi, która jest istotna dla tego pytania:

Czy muszę zrobić własną synchronizację, Jeśli używam Javy.util.ConcurrentLinkedQueue?

Operacje atomowe na współbieżnych kolekcjach są zsynchronizowane dla Ciebie. Innymi słowy, każde indywidualne wywołanie kolejki jest gwarantowane bez żadnych działań z twojej strony. Czym jest a nie gwarantowany thread-safe są wszelkie operacje wykonywane na zbiorze, które nie są atomowe.

Na przykład, jest to threadsafe bez żadnej akcji z twojej strony:

queue.add(obj);

Lub

queue.poll(obj);

Jednakże; nieatomiczne wywołania do kolejki nie są automatycznie bezpieczne dla wątków. Na przykład następujące operacje to , a nie automatycznie threadsafe:

if(!queue.isEmpty()) {
   queue.poll(obj);
}

Ten ostatni nie jest threadsafe, ponieważ jest bardzo możliwe, że pomiędzy wywołaniem time isEmpty a wywołaniem time poll, inne wątki będzie dodawać lub usuwać elementy z kolejki. Sposób wykonania threadsafe jest taki:

synchronized(queue) {
    if(!queue.isEmpty()) {
       queue.poll(obj);
    }
}
Znowu...atomowe wywołania do kolejki są automatycznie bezpieczne dla wątków. Nie atomowe nie są.
 33
Author: Jared,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:46

Użyj poll, aby uzyskać pierwszy element, a dodaj, aby dodać nowy ostatni element. To wszystko, żadnej synchronizacji ani niczego innego.

 6
Author: Hank Gay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-05 20:37:37

To jest prawdopodobnie to, czego szukasz pod względem bezpieczeństwa wątków i "ładności", gdy próbujesz pochłonąć wszystko w kolejce:

for (YourObject obj = queue.poll(); obj != null; obj = queue.poll()) {
}

Zagwarantuje to zamknięcie kolejki, gdy kolejka jest pusta i kontynuowanie usuwania z niej obiektów, o ile nie jest pusta.

 4
Author: marq,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-25 00:23:26

ConcurentLinkedQueue jest bardzo wydajną implementacją typu wait / lock (patrz javadoc w celach informacyjnych), więc nie tylko nie musisz synchronizować, ale Kolejka niczego nie zablokuje, dzięki czemu jest praktycznie tak szybka jak niezsynchronizowana (nie bezpieczna dla wątków).

 2
Author: siddhadev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-06 00:59:06

Po prostu użyj go tak, jak byś nie-równoległa kolekcja. Równoległe klasy [Collection] zawijają regularne Kolekcje, dzięki czemu nie musisz myśleć o synchronizacji dostępu.

Edit: ConcurrentLinkedList nie jest w rzeczywistości tylko opakowaniem, ale raczej lepszą implementacją współbieżną. Tak czy inaczej, nie musisz się martwić o synchronizację.

 1
Author: Ben S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-05 21:08:22