June 28, 2022

LinkedBlockingQueue in Java With Examples

LinkedBlockingQueue in Java is an implementation of BlockingQueue interface and is part of java.util.concurrent package. LinkedBlockingQueue has the features of both ArrayBlockingQueue and DelayQueue. ArrayBlockingQueue is a bounded blocking queue where as DelayQueue is an unbounded blocking queue. LinkedBlockingQueue sits in the middle as it 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.

LinkedBlockingQueue in Java

LinkedBlockingQueue is based on linked nodes where each node holds reference to the next node. Linked nodes are dynamically created upon each insertion unless this would bring the queue above capacity.

This queue orders elements FIFO (first-in-first-out). The head of the queue is that element that has been on the queue the longest time. The tail of the queue is that element that has been on the queue the shortest time. New elements are inserted at the tail of the queue, and the queue retrieval operations obtain elements at the head of the queue.

Features of LinkedBlockingQueue in Java

  1. LinkedBlockingQueue is an optionally-bounded blocking queue.
  2. Java LinkedBlockingQueue implementation is thread-safe. All queuing methods in the class achieve their effects atomically using ReentrantLock internally.
  3. LinkedBlockingQueue does not allow null elements. It throws NullPointerException on attempts to add, put or offer a null.
    public class LinkedBQ {
      public static void main(String[] args) {
        BlockingQueue bQueue = new LinkedBlockingQueue<>();
        try {
          // putting null
          bQueue.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.LinkedBlockingQueue.put(LinkedBlockingQueue.java:325)
    	at com.knpcode.programs.LinkedBQ.main(LinkedBQ.java:12)
    

Java LinkedBlockingQueue Constructors

  1. LinkedBlockingQueue()- Creates a LinkedBlockingQueue with a capacity of Integer.MAX_VALUE.
  2. LinkedBlockingQueue(int capacity)- Creates a LinkedBlockingQueue with the given (fixed) capacity.
  3. LinkedBlockingQueue(Collection<? extends E> c)- Creates a LinkedBlockingQueue with a capacity of Integer.MAX_VALUE, initially containing the elements of the given collection, added in traversal order of the collection's iterator.

LinkedBlockingQueue Java example

BlockingQueue implementations are designed to be used primarily for producer-consumer queues so let's see an example of producer-consumer using LinkedBlockingQueue.

We'll create an LinkedBlockingQueue of capacity 1 and use the put and take methods for insertion and retrieval operations respectively. These methods block the current thread indefinitely until the operation can succeed. Since the queue capacity is 1 so the insertion will be blocked until the element in the queue is consumed.

public class LinkedBQ {
  public static void main(String[] args) {        
    // shared queue
    BlockingQueue<Integer> bQueue = new LinkedBlockingQueue<>(1);
    ExecutorService executor = Executors.newFixedThreadPool(2);
    executor.execute(new LinkedProducer(bQueue));
    executor.execute(new LinkedConsumer(bQueue));
    executor.shutdown();
  }
}

// Producer
class LinkedProducer implements Runnable{
  BlockingQueue<Integer> bQueue;
  LinkedProducer(BlockingQueue<Integer> bQueue){
    this.bQueue = bQueue;
  }
  @Override
  public void run() {
    for(int i = 0; i < 5; i++){
      try {
        bQueue.put(i);
        System.out.println("Added to queue-" + i);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }
}
//Consumer
class LinkedConsumer implements Runnable{
  BlockingQueue<Integer> bQueue;
  LinkedConsumer(BlockingQueue<Integer> bQueue){
    this.bQueue = bQueue;
  }
  @Override
  public void run() {
    for(int i = 0; i < 5; i++){
      try {
        System.out.println("Consumer retrieved- " + bQueue.take());
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }
}
Output
Added to queue-0
Consumer retrieved- 0
Added to queue-1
Consumer retrieved- 1
Added to queue-2
Consumer retrieved- 2
Added to queue-3
Consumer retrieved- 3
Consumer retrieved- 4
Added to queue-4

LinkedBlockingQueue class methods

In BlockingQueue implementation like LinkedBlockingQueue 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
  • add(E e)- Inserts the specified element into this queue if it is possible to do so immediately without violating capacity restrictions, returning true upon success and throwing an IllegalStateException if no space is currently available.
  • offer(E e)- Inserts the specified element at the tail of this queue if it is possible to do so immediately without exceeding the queue's capacity, returning true upon success and false if this queue is full.
  • put(E e)- Inserts the specified element at the tail of this queue, waiting if necessary for space to become available.
  • offer(E e, long timeout, TimeUnit unit)- Inserts the specified element at the tail of this queue, waiting if necessary up to the specified wait time for space to become available.
Removal methods
  • remove()- Retrieves and removes the head of this queue. Throws NoSuchElementException if this queue is empty.
  • poll()- Retrieves and removes the head of this queue, or returns null if this queue is empty.
  • take()- Retrieves and removes the head of this queue, waiting if necessary until an element becomes available.
  • poll(long timeout, TimeUnit unit)- Retrieves and removes the head of this queue, waiting up to the specified wait time if necessary for an element to become available.
List of other important methods
  • clear()- Atomically removes all of the elements from this queue.
  • contains(Object o)- Returns true if this queue contains the specified element.
  • remainingCapacity()- Returns the number of additional elements that this queue can ideally (in the absence of memory or resource constraints) accept without blocking.
  • remove(Object o)- Removes a single instance of the specified element from this queue, if it is present.
  • size()- Returns the number of elements in this queue.
  • spliterator()- Returns a Spliterator over the elements in this queue.
  • toArray()- Returns an array containing all of the elements in this queue, in proper sequence.

That's all for the topic LinkedBlockingQueue 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