ConcurrentLinkedQueue in Java
ConcurrentLinkedQueue is a high-performance, thread-safe, non-blocking queue in Java.
It belongs to the java.util.concurrent package and is widely used for multi-threaded producer–consumer systems.
It uses a lock-free algorithm based on CAS (Compare-And-Swap), making it extremely fast in concurrent environments.
What is ConcurrentLinkedQueue?
A ConcurrentLinkedQueue is:
- A thread-safe, unbounded, non-blocking queue
- Based on a linked-node structure
- Follows FIFO (First In First Out) order
- Supports multiple threads inserting/removing simultaneously
- Uses lock-free CAS for high-speed operations
It is one of the most scalable queues in the JDK.
It implements the following:
Queue
ConcurrentLinkedQueue (class)
This makes it a powerful choice for multi-producer and multi-consumer environments.
Why Is ConcurrentLinkedQueue So Fast? (Internal Working)
ConcurrentLinkedQueue internally uses:
1. Linked Nodes
Each element is wrapped inside a linked node (like LinkedList).
2. CAS (Compare-And-Swap) Atomic Updates
Instead of locks, it uses CAS to:
- Add elements at the tail
- Remove elements from the head
This means:
- No locking
- No waiting
- No thread blocking
- Extremely low latency
- Multiple threads can operate simultaneously
Operations like offer() and poll() run in O(1) average time.
Features of ConcurrentLinkedQueue

1. Thread-Safe (Without Locks)
It achieves thread safety using atomic operations, not synchronized or ReentrantLocks.
2. FIFO Ordering
Elements are processed in the order they were inserted.
3. Unbounded Queue
It expands automatically depending on system memory.
4. High-Performance
Designed for heavily concurrent environments with minimal contention.
5. Weakly Consistent Iterators
Iteration:
- Does not block other operations
- Does not throw ConcurrentModificationException
- May not reflect real-time updates (acceptable in concurrent algorithms)
6. Non-Blocking Behavior
Methods like offer(), poll(), and peek() never block.
Common Methods of ConcurrentLinkedQueue
| Method | Description |
|---|---|
| offer(e) | Adds element at the tail (always succeeds) |
| add(e) | Same as offer(), but may throw exception if fails |
| poll() | Removes and returns head, or null if empty |
| peek() | Returns head without removing (or null) |
| isEmpty() | Checks if queue is empty |
| size() | Returns count (but expensive & approximate) |
| iterator() | Returns weakly consistent iterator |
Basic Example of ConcurrentLinkedQueue
import java.util.concurrent.ConcurrentLinkedQueue;
public class Main {
public static void main(String[] args) {
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
queue.offer("A");
queue.offer("B");
queue.offer("C");
System.out.println("Queue: " + queue);
System.out.println("Poll: " + queue.poll());
System.out.println("Poll: " + queue.poll());
System.out.println("After Poll: " + queue);
System.out.println("Peek: " + queue.peek());
}
}
Output
Queue: [A, B, C]
Poll: A
Poll: B
After Poll: [C]
Peek: C
Multi-Threaded Example (Producers)
import java.util.concurrent.ConcurrentLinkedQueue;
public class Demo {
public static void main(String[] args) {
ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<>();
Runnable producer = () -> {
for (int i = 1; i <= 5; i++) {
queue.offer(i);
}
};
Thread t1 = new Thread(producer);
Thread t2 = new Thread(producer);
t1.start();
t2.start();
}
}
- No locks
- No synchronization required
- Threads never block
When Should You Use ConcurrentLinkedQueue?
Use it when you need:
- High-throughput message passing
- Low-latency communication between threads
- Non-blocking producer-consumer systems
- Multi-threaded queues without waiting
- Real-time data processing
Perfect for:
- Messaging/event queue
- Task scheduling systems
- Job dispatchers
- Real-time analytics
- Web server request pipelines
- Work-sharing systems
ConcurrentLinkedQueue vs LinkedBlockingQueue
| Feature | ConcurrentLinkedQueue | LinkedBlockingQueue |
|---|---|---|
| Blocking | No | Yes |
| Capacity | Unbounded | Bounded/Unbounded |
| Locking | Lock-free (CAS) | Uses locks |
| Performance | Very fast | Slower under high concurrency |
| Use Case | Non-blocking apps | Producer-consumer with waiting |
Advantages of ConcurrentLinkedQueue
- Extremely fast in concurrent environments
- No locking overhead
- Non-blocking, low-latency
- Unlimited size
- Safe multi-threading
- Iterators never fail
Disadvantages
size()is slow and approximate- No blocking methods (
put(),take()not available) - Not suitable when you need backpressure (bounded queue)
Points to Remember
ConcurrentLinkedQueue is ideal when:
- You need fast, scalable, non-blocking queue communication
- Multiple threads add/remove elements simultaneously
- You want to avoid locking overhead
It’s a top choice for modern concurrent systems, high-performance backends, and real-time applications.
