LinkedBlockingDeque in Java

In Java, a Deque (Double Ended Queue) is a data structure that allows insertion and removal of elements from both ends, i.e., the front and the back. The LinkedBlockingDeque is a class in Java that implements the Deque interface and provides a linked list implementation of a Deque that is thread-safe and can be used in a multi-threaded environment.

LinkedBlockingDeque Class


The LinkedBlockingDeque class is part of the java.util.concurrent package and implements the Deque interface. It is a bounded blocking Deque, which means that it has a maximum capacity and blocks the insertion operation when the Deque is full and the removal operation when the Deque is empty. The LinkedBlockingDeque has the following constructors:

  1. LinkedBlockingDeque() – Creates an empty LinkedBlockingDeque with an initial capacity of Integer.MAX_VALUE.
  2. LinkedBlockingDeque(int capacity) – Creates an empty LinkedBlockingDeque with the given capacity.
  3. LinkedBlockingDeque(Collection c) – Creates a LinkedBlockingDeque with the same elements as the given collection.


Thread Safety


The LinkedBlockingDeque is thread-safe and can be used in a multi-threaded environment. The Deque supports concurrent access by multiple threads without the need for external synchronization. The Deque provides blocking operations that block the calling thread until the operation can be performed, which makes it useful for producer-consumer scenarios.

Blocking Operations


The LinkedBlockingDeque provides blocking operations that block the calling thread until the operation can be performed. The following blocking operations are provided:

  1. addFirst(E e) – Inserts the specified element at the front of the deque, waiting if necessary for space to become available.
  2. addLast(E e) – Inserts the specified element at the end of the deque, waiting if necessary for space to become available.
  3. offerFirst(E e, long timeout, TimeUnit unit) – Inserts the specified element at the front of the deque, waiting up to the specified timeout for space to become available.
  4. offerLast(E e, long timeout, TimeUnit unit) – Inserts the specified element at the end of the deque, waiting up to the specified timeout for space to become available.
  5. takeFirst() – Retrieves and removes the first element of the deque, waiting if necessary for an element to become available.
  6. takeLast() – Retrieves and removes the last element of the deque, waiting if necessary for an element to become available.
  7. pollFirst(long timeout, TimeUnit unit) – Retrieves and removes the first element of the deque, waiting up to the specified timeout if necessary for an element to become available.
  8. pollLast(long timeout, TimeUnit unit) – Retrieves and removes the last element of the deque, waiting up to the specified timeout if necessary for an element to become available.


Iterator


The LinkedBlockingDeque provides a fail-fast iterator that throws a ConcurrentModificationException if the deque is modified during iteration. The iterator of a LinkedBlockingDeque is weakly consistent, which means that it does not necessarily reflect the latest state of the deque.

Example Usage
Here is an example usage of a LinkedBlockingDeque:

import java.util.concurrent.LinkedBlockingDeque;

public class LinkedBlockingDequeExample {
public static void main(String[] args) {
    LinkedBlockingDeque<Integer> deque = new LinkedBlockingDeque<>(3);

    deque.addLast(1);
    deque.addLast(2);
    deque.addLast(3);

    System.out.println("Deque: " + deque);

    try {
        deque.addLast(4); // Blocks the thread as the deque is full
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    int first = deque.takeFirst();
    System.out.println("Removed first element: " + first);

    deque.addLast(4);
    System.out.println("Deque: " + deque);
try {
    deque.addFirst(5, 2, TimeUnit.SECONDS); // Blocks the thread for 2 seconds as the deque is full
} catch (InterruptedException e) {
    e.printStackTrace();
}

int last = deque.takeLast();
System.out.println("Removed last element: " + last);

System.out.println("Deque: " + deque);
}
}


Output:

Deque: [1, 2, 3]
Removed first element: 1
Deque: [2, 3, 4]
Removed last element: 4
Deque: [2, 3, 5]

Conclusion


The LinkedBlockingDeque class provides a thread-safe implementation of a Deque that supports concurrent access by multiple threads. It provides blocking operations that block the calling thread until the operation can be performed, which makes it useful for producer-consumer scenarios. The LinkedBlockingDeque is a useful data structure for multi-threaded applications that require a Deque with a maximum capacity.


The Deque provides both insertion and removal operations from both ends, making it a useful data structure for implementing a queue, stack, or double-ended queue. The LinkedBlockingDeque is a useful alternative to the ArrayDeque when a thread-safe implementation is required, and blocking operations are needed.

One thing to keep in mind while using a LinkedBlockingDeque is that blocking operations may cause the calling thread to wait indefinitely if the operation cannot be performed. Therefore, it is important to choose the appropriate blocking operation that meets the requirements of your application.

Overall, the LinkedBlockingDeque is a powerful data structure that provides a thread-safe implementation of a Deque with blocking operations. It is a useful addition to the Java Collections Framework and is a must-have tool for multi-threaded applications that require a bounded Deque.