C

Core Java tutorial for beginners

Clean • Professional

ConcurrentLinkedDeque in Java – Lock-Free Deque with Examples

3 minute

ConcurrentLinkedDeque in Java

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.


What Is ConcurrentLinkedDeque?

A ConcurrentLinkedDeque is:

  • Thread-safe (for multi-threaded use)
  • Lock-free (uses CAS operations)
  • Unbounded (grows automatically)
  • Allows operations at head + tail
  • Ideal for work-stealing & task scheduling
  • Internally uses linked nodes
  • Provides weakly consistent iterators

It implements:

  • Deque
  • Queue

Compared to ConcurrentLinkedQueue, this deque supports double-ended operations.


Internal Working of ConcurrentLinkedDeque

1. Linked Nodes

Each element is stored in a node containing:

  • prev pointer
  • next pointer

It behaves like a thread-safe doubly linked list.

2. Lock-Free with CAS

All operations (add/remove) use CAS – Compare-And-Swap, so:

  • No thread blocking
  • No locking
  • Very high concurrency
  • Low latency

Multiple threads can operate simultaneously on both ends.


Key Features of ConcurrentLinkedDeque

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

  • Does NOT throw ConcurrentModificationException
  • Reflects updates during iteration
  • Never freezes while other threads update

6. Highly Scalable

Excellent for concurrent task processing.


Common Methods of ConcurrentLinkedDeque

Adding Elements

MethodDescription
addFirst(e)Insert at head
addLast(e)Insert at tail
offerFirst(e)Add at head (non-throwing)
offerLast(e)Add at tail

Removing Elements

MethodDescription
pollFirst()Remove & return head
pollLast()Remove & return tail
removeFirst()Throw exception if empty
removeLast()Throw exception if empty

Peeking Elements

MethodDescription
peekFirst()View head
peekLast()View tail
peek()Same as peekFirst

Other Methods

  • isEmpty()
  • iterator()
  • descendingIterator()
  • size() (approximate, slow)

Simple Example: Using ConcurrentLinkedDeque

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

Multi-Threaded Example

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();
    }
}
  • No locks
  • No synchronization needed
  • Perfect for parallel producers

When to Use ConcurrentLinkedDeque?

Use it when you need:

  • Non-blocking double-ended queue
  • High throughput
  • Multiple producers/consumers
  • Insert/remove from both ends
  • Work-stealing frameworks
  • Actor-based systems
  • Multi-core task scheduling

Common Use Cases

  • Work-stealing algorithms
  • Real-time task schedulers
  • Server request pipelines
  • Background job processors
  • Messaging/event systems
  • Highly parallel applications

ConcurrentLinkedDeque vs ConcurrentLinkedQueue

FeatureConcurrentLinkedDequeConcurrentLinkedQueue
Ends supportedHead + TailTail only
StructureDouble-endedSingle-ended
OperationsMore (first/last)Limited
Use CaseWork-stealing, flexible tasksBasic producer-consumer
PerformanceSimilarSimilar

ConcurrentLinkedDeque vs LinkedBlockingDeque

FeatureConcurrentLinkedDequeLinkedBlockingDeque
Thread safetyYesYes
ImplementationLock-freeBlocking
Blocking opsNoYes (take(), put())
CapacityUnboundedBounded
PerformanceFasterSlower due to locks
Best forHigh-speed concurrencyProducer-consumer blocking

Advantages

  • Extremely fast (lock-free)
  • Thread-safe
  • FIFO + LIFO both possible
  • Unbounded
  • Weakly consistent iterators
  • Ideal for concurrent task processing

Disadvantages

  • No blocking operations
  • size() is slow & approximate
  • Not suitable when capacity control is required

Points to Remember

ConcurrentLinkedDeque is the best choice when you need:

  • A high-performance, lock-free deque
  • Fast operations from both ends
  • Maximum concurrency
  • Scalable task management
  • Real-time processing in multi-core systems

It is widely used in modern concurrent frameworks, high-speed servers, and parallel computing systems.

Article 0 of 0