Author
ConcurrentLinkedDeque is a high-performance, thread-safe, non-blocking, unbounded double-ended queue in Java.
It belongs to the java.util.concurrent package and is used when multiple threads must insert or remove elements from both ends without locking.
It is one of the most scalable concurrent data structures in Java.
A ConcurrentLinkedDeque is:
It implements:
Compared to ConcurrentLinkedQueue, this deque supports double-ended operations.
1. Linked Nodes
Each element is stored in a node containing:
prev pointernext pointerIt behaves like a thread-safe doubly linked list.
2. Lock-Free with CAS
All operations (add/remove) use CAS – Compare-And-Swap, so:
Multiple threads can operate simultaneously on both ends.
1. Thread-Safe
Designed for multi-threaded usage.
2. Lock-Free Performance
No synchronized blocks → extremely fast.
3. Double-Ended
Supports:
addFirst(), pollFirst()addLast(), pollLast()4. Unbounded
Automatically expands as needed.
5. Weakly Consistent Iterator
ConcurrentModificationException6. Highly Scalable
Excellent for concurrent task processing.
Adding Elements
| Method | Description |
|---|---|
addFirst(e) | Insert at head |
addLast(e) | Insert at tail |
offerFirst(e) | Add at head (non-throwing) |
offerLast(e) | Add at tail |
Removing Elements
| Method | Description |
|---|---|
pollFirst() | Remove & return head |
pollLast() | Remove & return tail |
removeFirst() | Throw exception if empty |
removeLast() | Throw exception if empty |
Peeking Elements
| Method | Description |
|---|---|
peekFirst() | View head |
peekLast() | View tail |
peek() | Same as peekFirst |
Other Methods
isEmpty()iterator()descendingIterator()size() (approximate, slow)import java.util.concurrent.ConcurrentLinkedDeque;
public class Main {
public static void main(String[] args) {
ConcurrentLinkedDeque<String> deque = new ConcurrentLinkedDeque<>();
deque.addFirst("A");
deque.addLast("B");
deque.addLast("C");
System.out.println("Deque: " + deque);
System.out.println("Poll First: " + deque.pollFirst()); // A
System.out.println("Poll Last: " + deque.pollLast()); // C
System.out.println("After Poll: " + deque);
System.out.println("Peek First: " + deque.peekFirst()); // B
}
}
Output
Deque: [A, B, C]
Poll First: A
Poll Last: C
After Poll: [B]
Peek First: B
import java.util.concurrent.ConcurrentLinkedDeque;
public class Demo {
public static void main(String[] args) {
ConcurrentLinkedDeque<Integer> deque = new ConcurrentLinkedDeque<>();
Runnable task = () -> {
for (int i = 1; i <= 5; i++) {
deque.offerLast(i);
}
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
}
}
Use it when you need:
| Feature | ConcurrentLinkedDeque | ConcurrentLinkedQueue |
|---|---|---|
| Ends supported | Head + Tail | Tail only |
| Structure | Double-ended | Single-ended |
| Operations | More (first/last) | Limited |
| Use Case | Work-stealing, flexible tasks | Basic producer-consumer |
| Performance | Similar | Similar |
| Feature | ConcurrentLinkedDeque | LinkedBlockingDeque |
|---|---|---|
| Thread safety | Yes | Yes |
| Implementation | Lock-free | Blocking |
| Blocking ops | No | Yes (take(), put()) |
| Capacity | Unbounded | Bounded |
| Performance | Faster | Slower due to locks |
| Best for | High-speed concurrency | Producer-consumer blocking |
size() is slow & approximateConcurrentLinkedDeque is the best choice when you need:
It is widely used in modern concurrent frameworks, high-speed servers, and parallel computing systems.