Understanding LinkedBlockingDeque: Structure, Core Operations, and Example Usage
This article explains the design and implementation of Java's LinkedBlockingDeque, covering its internal doubly‑linked list structure, key fields, constructors, core methods for adding, removing, and traversing elements, and provides a multithreaded example that demonstrates its thread‑safety compared to non‑concurrent collections.
LinkedBlockingDeque is a thread‑safe double‑ended blocking queue implemented with a doubly‑linked list, supporting both FIFO and FILO operations.
Key internal fields : first (head node), last (tail node), count (current size), capacity (optional maximum size), lock (a ReentrantLock), notEmpty and notFull (conditions used for blocking behavior).
Constructor creates an empty deque with a specified capacity and validates the argument:
public LinkedBlockingDeque(int capacity) {
if (capacity <= 0) throw new IllegalArgumentException();
this.capacity = capacity;
}Adding elements – the public offer(E e) method simply delegates to offerLast(e), which creates a new node, acquires the lock, and calls linkLast(node):
public boolean offer(E e) {
return offerLast(e);
}
public boolean offerLast(E e) {
if (e == null) throw new NullPointerException();
Node<E> node = new Node<E>(e);
final ReentrantLock lock = this.lock;
lock.lock();
try {
return linkLast(node);
} finally {
lock.unlock();
}
}
private boolean linkLast(Node<E> node) {
if (count >= capacity) return false;
Node<E> l = last;
node.prev = l;
last = node;
if (first == null)
first = node;
else
l.next = node;
++count;
notEmpty.signal();
return true;
}Removing elements – take() forwards to takeFirst(), which locks the deque, waits on notEmpty until a node is available, then calls unlinkFirst() to detach the head node:
public E take() throws InterruptedException {
return takeFirst();
}
public E takeFirst() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
E x;
while ((x = unlinkFirst()) == null)
notEmpty.await();
return x;
} finally {
lock.unlock();
}
}
private E unlinkFirst() {
Node<E> f = first;
if (f == null) return null;
Node<E> n = f.next;
E item = f.item;
f.item = null;
f.next = f; // help GC
first = n;
if (n == null)
last = null;
else
n.prev = null;
--count;
notFull.signal();
return item;
}Traversal – iterator() returns a new Itr object that extends AbstractItr. The iterator safely walks the list under the deque’s lock, skipping nodes whose item has been cleared.
public Iterator<E> iterator() {
return new Itr();
}
private class Itr extends AbstractItr {
Node<E> firstNode() { return first; }
Node<E> nextNode(Node<E> n) { return n.next; }
}
private abstract class AbstractItr implements Iterator<E> {
Node<E> next;
E nextItem;
Node<E> lastRet;
abstract Node<E> firstNode();
abstract Node<E> nextNode(Node<E> n);
// ... implementation of hasNext(), next(), remove() ...
}Example usage demonstrates two threads concurrently adding strings to a LinkedBlockingDeque and printing its contents. When the deque is used, the program runs without errors; replacing it with a non‑thread‑safe LinkedList causes a ConcurrentModificationException.
import java.util.*;
import java.util.concurrent.*;
public class LinkedBlockingDequeDemo1 {
private static Queue<String> queue = new LinkedBlockingDeque<>();
public static void main(String[] args) {
new MyThread("ta").start();
new MyThread("tb").start();
}
private static void printAll() {
for (String v : queue) System.out.print(v + ", ");
System.out.println();
}
private static class MyThread extends Thread {
MyThread(String name) { super(name); }
@Override public void run() {
for (int i = 1; i <= 6; i++) {
String val = Thread.currentThread().getName() + i;
queue.add(val);
printAll();
}
}
}
}The output shows interleaved additions from both threads, confirming that LinkedBlockingDeque handles concurrent modifications correctly.
Big Data Technology & Architecture
Wang Zhiwu, a big data expert, dedicated to sharing big data technology.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
