Java > Java Collections Framework > Queue and Deque > BlockingQueue and ConcurrentQueue
ConcurrentLinkedQueue Example
This example demonstrates the use of ConcurrentLinkedQueue
, a non-blocking, thread-safe queue. Unlike BlockingQueue
, it doesn't block threads when the queue is empty or full. It is useful for scenarios where you want to avoid blocking and need high concurrency.
Code Implementation
This code demonstrates a producer-consumer scenario using ConcurrentLinkedQueue
. The producer1
thread adds messages to the queue using queue.offer()
, and the consumer1
thread retrieves messages using queue.poll()
. The poll()
method returns null
if the queue is empty, so the consumer checks for null
before processing. This demonstrates the non-blocking nature of ConcurrentLinkedQueue
.
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
public class ConcurrentLinkedQueueExample {
public static void main(String[] args) throws InterruptedException {
Queue<String> queue = new ConcurrentLinkedQueue<>();
Thread producer1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
queue.offer("Message-" + i);
System.out.println("Produced: Message-" + i);
try {
Thread.sleep(100); // Simulate production time
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
Thread consumer1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
String message = queue.poll();
if (message != null) {
System.out.println("Consumed: " + message);
} else {
System.out.println("Queue is empty.");
}
try {
Thread.sleep(200); // Simulate consumption time
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
producer1.start();
consumer1.start();
producer1.join();
consumer1.join();
System.out.println("Queue size: " + queue.size());
}
}
Concepts Behind the Snippet
Real-Life Use Case
ConcurrentLinkedQueue
is suitable for high-throughput scenarios where blocking is unacceptable. Examples include event processing systems, asynchronous logging, and data ingestion pipelines where the rate of production and consumption fluctuates significantly. It's good for multi-threaded application like a chat application where a server receives messages and broadcasts them in real-time.
Best Practices
poll()
returns null
when the queue is empty, ensure your consumer handles this case appropriately.
Interview Tip
Understand the difference between blocking and non-blocking queues and when to use each. Be prepared to discuss the trade-offs between ConcurrentLinkedQueue
and BlockingQueue
implementations.
When to Use Them
Use ConcurrentLinkedQueue
when you need a thread-safe queue that doesn't block and high concurrency is critical. It's suitable when producers and consumers operate independently and blocking would negatively impact performance.
Memory Footprint
ConcurrentLinkedQueue
is unbounded, so its memory footprint grows dynamically as elements are added. Monitor the queue size to prevent excessive memory consumption, especially in long-running applications.
Alternatives
Pros
Cons
FAQ
-
What happens if I try to poll from an empty
ConcurrentLinkedQueue
?
Thepoll()
method returnsnull
. -
Is
ConcurrentLinkedQueue
suitable for all concurrent scenarios?
No. It's best suited for scenarios where blocking is undesirable. If blocking is acceptable and simplifies your code, aBlockingQueue
might be a better choice. -
How does
ConcurrentLinkedQueue
ensure thread safety?
It uses lock-free algorithms based on Compare-and-Swap (CAS) operations. This avoids the overhead of explicit locking.