June 28, 2022

LinkedBlockingDeque in Java With Examples

LinkedBlockingDeque in Java is an implementation of BlockingDeque interface and is part of java.util.concurrent package. LinkedBlockingDeque, just like LinkedBlockingQueue, is an optionally-bounded blocking queue which means the capacity for the queue can be specified thus making it bounded or it can be left unspecified in which case capacity of the deque is Integer.MAX_VALUE.

LinkedBlockingDeque in Java

LinkedBlockingDeque is based on linked nodes where each node holds reference to both previous and next nodes. Linked nodes are dynamically created upon each insertion unless this would bring the deque above capacity.

Since LinkedBlockingDeque is a deque (double ended queue) elements can be inserted and removed from both ends of the queue that is how LinkedBlockingDeque differs from the BlockingQueue implementations like ArrayBlockingQueue where elements are added to the end of the queue and retrieved from the head of the queue.

LinkedBlockingDeque implementation is thread-safe. All queuing methods in the class achieve their effects atomically using ReentrantLock internally.

Java LinkedBlockingDeque constructors

  • LinkedBlockingDeque()- When no capacity is specified LinkedBlockingDeque is created with a capacity of Integer.MAX_VALUE.
  • LinkedBlockingDeque(int capacity)- Creates a LinkedBlockingDeque with the given (fixed) capacity.
  • LinkedBlockingDeque(Collection<? extends E> c)- Creates a LinkedBlockingDeque with a capacity of Integer.MAX_VALUE, initially containing the elements of the given collection, added in traversal order of the collection's iterator.

LinkedBlockingDeque does not allow null elements

Implementations of BlockingDeque does not allow null elements.

public class LBDDemo {
  public static void main(String[] args) {
    BlockingDeque<Integer> blockingDeque = new LinkedBlockingDeque<>();
    try {
      blockingDeque.put(10);
      blockingDeque.put(null);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}
Output
Exception in thread "main" java.lang.NullPointerException
	at java.base/java.util.concurrent.LinkedBlockingDeque.putLast(LinkedBlockingDeque.java:381)
	at java.base/java.util.concurrent.LinkedBlockingDeque.put(LinkedBlockingDeque.java:640)
	at com.knpcode.programs.LBDDemo.main(LBDDemo.java:12)

LinkedBlockingDeque Java example

Here is a producer-consumer example using the LinkedBlockingDeque. Each producer thread put 5 integer values in the queue where as consumer thread retrieves those values from the queue. Thread pool is only of two threads and the consumer blocks if consumer is executed first, for that takeLast() method is used.

public class LBDDemo {
  public static void main(String[] args) {
    BlockingDeque<Integer> blockingDeque = new LinkedBlockingDeque<>();
    ExecutorService executor = Executors.newFixedThreadPool(2);
    // 2 producer threads and one consumer thread
    executor.execute(new LinkedDQProducer(blockingDeque));
    executor.execute(new LinkedDQProducer(blockingDeque));
    executor.execute(new LinkedDQConsumer(blockingDeque));
    executor.shutdown();
  }
}    
// Producer
class LinkedDQProducer implements Runnable{
  BlockingDeque<Integer> blockingDeque;
  LinkedDQProducer(BlockingDeque<Integer> blockingDeque){
    this.blockingDeque = blockingDeque;
  }
  @Override
  public void run() {
    for(int i = 0; i < 5; i++){            
      blockingDeque.addFirst(i);
      System.out.println("Added to queue-" + i);            
    }
  }
}

//Consumer
class LinkedDQConsumer implements Runnable{
  BlockingDeque<Integer> blockingDeque;
  LinkedDQConsumer(BlockingDeque<Integer> blockingDeque){
    this.blockingDeque = blockingDeque;
  }
  @Override
  public void run() {
    for(int i = 0; i < 10; i++){
      try {
        System.out.println("Consumer retrieved- " + blockingDeque.takeLast());
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }
}
Output
Added to queue-0
Added to queue-0
Added to queue-1
Added to queue-1
Added to queue-2
Added to queue-3
Added to queue-4
Consumer retrieved- 0
Consumer retrieved- 0
Consumer retrieved- 1
Consumer retrieved- 1
Consumer retrieved- 2
Consumer retrieved- 3
Consumer retrieved- 4
Added to queue-2
Added to queue-3
Consumer retrieved- 2
Added to queue-4
Consumer retrieved- 3
Consumer retrieved- 4

Java LinkedBlockingDeque class methods

In BlockingDeque implementation like LinkedBlockingDeque methods for adding and removing an element come in four forms-

One throws an exception, the second returns a special value (either null or false, depending on the operation), the third blocks the current thread indefinitely until the operation can succeed, and the fourth blocks for only a given maximum time limit before giving up.

Insertion methods
  • addFirst(E e)- Inserts the specified element at the front of this deque if it is possible to do so immediately without violating capacity restrictions, throwing an IllegalStateException if no space is currently available.
  • addLast(E e)- Inserts the specified element at the end of this deque if it is possible to do so immediately without violating capacity restrictions, throwing an IllegalStateException if no space is currently available.
  • offerFirst(E e)- Inserts the specified element at the front of this deque if it is possible to do so immediately without violating capacity restrictions, returning true upon success and false if no space is currently available.
  • offerLast(E e)- Inserts the specified element at the end of this deque if it is possible to do so immediately without violating capacity restrictions, returning true upon success and false if no space is currently available.
  • putFirst(E e)- Inserts the specified element at the front of this deque, waiting if necessary for space to become available.
  • putLast(E e)- Inserts the specified element at the end of this deque, waiting if necessary for space to become available.
  • offerFirst(E e, long timeout, TimeUnit unit)- Inserts the specified element at the front of this deque, waiting up to the specified wait time if necessary for space to become available.
  • offerLast(E e, long timeout, TimeUnit unit)- Inserts the specified element at the end of this deque, waiting up to the specified wait time if necessary for space to become available.
Removal methods
  • removeFirst()- Retrieves and removes the first element of this deque. Throws an exception if this deque is empty.
  • removeLast()- Retrieves and removes the last element of this deque. Throws an exception if this deque is empty.
  • pollFirst()- Retrieves and removes the first element of this deque, or returns null if this deque is empty.
  • pollLast()- Retrieves and removes the last element of this deque, or returns null if this deque is empty.
  • takeFirst()- Retrieves and removes the first element of this deque, waiting if necessary until an element becomes available.
  • takeLast()- Retrieves and removes the last element of this deque, waiting if necessary until an element becomes available.
  • pollFirst(long timeout, TimeUnit unit)- Retrieves and removes the first element of this deque, waiting up to the specified wait time if necessary for an element to become available.
  • pollLast(long timeout, TimeUnit unit)- Retrieves and removes the last element of this deque, waiting up to the specified wait time if necessary for an element to become available.

That's all for the topic LinkedBlockingDeque in Java With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

No comments:

Post a Comment