Why would I use ConcurrentLinkedQueue
when I have LinkedBlockingQueue
? I know ConcurrentLinkedQueue
is non blocking but LinkedBlockingQueue
can be worked as ConcurrentLinkedQueue
. I would use put()
/offer()
method for insertion and poll()
method for removal. poll()
method does not wait if queue is empty. LinkedBlockingQueue
is unbounded as well. So I can use this.
The difference I found so far is ConcurrentLinkedQueue
is using hardware level synchronization mechanism with compare and swap while LinkedBlockingQueue
is using ReentrantLock
.
LinkedBlockingQueue blocks the consumer or the producer when the queue is empty or full and the respective consumer/producer thread is put to sleep.
ConcurrentLinkedQueue is an unbounded thread-safe queue which arranges the element in FIFO. New elements are added at the tail of this queue and the elements are added from the head of this queue. ConcurrentLinkedQueue class and its iterator implements all the optional methods of the Queue and Iterator interfaces.
Here we have a blockingQueue that has a capacity equal to 10. It means that when a producer tries to add an element to an already full queue, depending on a method that was used to add it (offer(), add() or put()), it will block until space for inserting object becomes available. Otherwise, the operations will fail.
The main difference is that ConcurrentLinkedQueue
is wait-free, not merely lock-free (what's the difference?) while LinkedBlockingQueue
must remain locking by its very nature.
You can model ConcurrentLinkedQueue
with LinkedBlockingQueue
and poll
, but the implementation would remain locking, reducing the concurrency that you could get out of your system.
Here is an admittedly imprecise microbenchmark that checks the speed of passing 10,000 objects through each of the two concurrent queues without blocking, and counting the total number of calls to poll()
in a loop:
AtomicInteger total = new AtomicInteger();
ConcurrentLinkedQueue<Integer> q = new ConcurrentLinkedQueue<>();
Thread thread = new Thread(() -> {
int remaining = 10000;
while (remaining != 0) {
total.incrementAndGet();
if (q.poll() != null) {
remaining--;
}
}
});
Integer[] first100 = new Integer[100];
for (int i = 0 ; i != 100 ; i++) {
first100[i] = i;
}
long start = System.nanoTime();
thread.start();
for (int i = 0 ; i != 10000 ; i++) {
q.add(first100[i%100]);
}
thread.join();
long runtime = System.nanoTime() - start;
The idea is to measure queue's "throughput" in the absence of other processing. This task completes in 11.23 ms with 60K iterations in the reading thread (demo 1) with ConcurrentLinkedQueue
, and 23,46 ms / 100K iterations with LinkedBlockingQueue
(demo 2).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With