Java BlockingQueue

Jakob Jenkov
Last update: 2021-03-22

The Java BlockingQueue interface, java.util.concurrent.BlockingQueue, represents a queue which is thread safe to put elements into, and take elements out of from. In other words, multiple threads can be inserting and taking elements concurrently from a Java BlockingQueue, without any concurrency issues arising.

The term blocking queue comes from the fact that the Java BlockingQueue is capable of blocking the threads that try to insert or take elements from the queue. For instance, if a thread tries to take an element and there are none left in the queue, the thread can be blocked until there is an element to take. Whether or not the calling thread is blocked depends on what methods you call on the BlockingQueue. The different methods are explained in more detail later.

This text will not discuss how to implement a BlockingQueue in Java yourself. If you are interested in that, I have a text on Blocking Queues in my more theoretical Java Concurrency Tutorial.

Java BlockingQueue Tutorial Video

If you prefer video, I have a video version of this tutorial here: Java BlockingQueue Tutorial

Java BlockingQueue Tutorial Video

BlockingQueue Implementations

Since BlockingQueue is an interface, you need to use one of its implementations to use it. The java.util.concurrent package has the following implementations of the BlockingQueue interface:

Click the links in the list to read more about each implementation.

BlockingQueue Usage

A BlockingQueue is typically used to have one thread produce objects, which another thread consumes. Here is a diagram that illustrates this principle:

A BlockingQueue with one thread putting into it, and another thread taking from it.
A BlockingQueue with one thread putting into it, and another thread taking from it.

The producing thread will keep producing new objects and insert them into the BlockingQueue, until the queue reaches some upper bound on what it can contain. It's limit, in other words. If the blocking queue reaches its upper limit, the producing thread is blocked while trying to insert the new object. It remains blocked until a consuming thread takes an object out of the queue.

The consuming thread keeps taking objects out of the BlockingQueue to processes them. If the consuming thread tries to take an object out of an empty queue, the consuming thread is blocked until a producing thread puts an object into the queue.


BlockingQueue Methods

The Java BlockingQueue interface has 4 different sets of methods for inserting, removing and examining the elements in the queue. Each set of methods behaves differently in case the requested operation cannot be carried out immediately. Here is a table of the methods:

  Throws Exception Special Value Blocks Times Out
Insert add(o) offer(o) put(o) offer(o, timeout, timeunit)
Remove remove(o) poll() take() poll(timeout, timeunit)
Examine element() peek()    

The 4 different sets of behaviour means this:

  1. Throws Exception:
    If the attempted operation is not possible immediately, an exception is thrown.
  2. Special Value:
    If the attempted operation is not possible immediately, a special value is returned (often true / false).
  3. Blocks:
    If the attempted operation is not possible immedidately, the method call blocks until it is.
  4. Times Out:
    If the attempted operation is not possible immedidately, the method call blocks until it is, but waits no longer than the given timeout. Returns a special value telling whether the operation succeeded or not (typically true / false).

It is not possible to insert null into a BlockingQueue. If you try to insert null, the BlockingQueue will throw a NullPointerException.

It is also possible to access all the elements inside a BlockingQueue, and not just the elements at the start and end. For instance, say you have queued an object for processing, but your application decides to cancel it. You can then call e.g. remove(o) to remove a specific object in the queue. However, this is not done very efficiently, so you should not use these Collection methods unless you really have to.

Java BlockingQueue Example

Here is a Java BlockingQueue example. The example uses the ArrayBlockingQueue implementation of the BlockingQueue interface.

First, the BlockingQueueExample class which starts a Producer and a Consumer in separate threads. The Producer inserts strings into a shared BlockingQueue, and the Consumer takes them out.

public class BlockingQueueExample {

    public static void main(String[] args) throws Exception {

        BlockingQueue queue = new ArrayBlockingQueue(1024);

        Producer producer = new Producer(queue);
        Consumer consumer = new Consumer(queue);

        new Thread(producer).start();
        new Thread(consumer).start();

        Thread.sleep(4000);
    }
}

Here is the Producer class. Notice how it sleeps a second between each put() call. This will cause the Consumer to block, while waiting for objects in the queue.

public class Producer implements Runnable{

    protected BlockingQueue queue = null;

    public Producer(BlockingQueue queue) {
        this.queue = queue;
    }

    public void run() {
        try {
            queue.put("1");
            Thread.sleep(1000);
            queue.put("2");
            Thread.sleep(1000);
            queue.put("3");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Here is the Consumer class. It just takes out the objects from the queue, and prints them to System.out.

public class Consumer implements Runnable{

    protected BlockingQueue queue = null;

    public Consumer(BlockingQueue queue) {
        this.queue = queue;
    }

    public void run() {
        try {
            System.out.println(queue.take());
            System.out.println(queue.take());
            System.out.println(queue.take());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

add()

The Java BlockingQueue add() method will add the element passed as parameter to this method if the BlockingQueue has space for it internally. If the BlockingQueue does not have space internally for this new element, the add() method throws an IllegalStateException.

offer()

The BlockingQueue offer() method will add the element passed as parameter to this method if the BlockingQueue has space for it internally. If the BlockingQueue does not have space internally for this new element, the offer() method return false.

offer(long millis, TimeUnit timeUnit)

The BlockingQueue offer() method exists in a version which takes a time out as parameter. This version of the offer() method will add the element passed as parameter if the BlockingQueue has space for it internally, or space becomes available. If the BlockingQueue does not have or get space internally for this new element within the time out, this version of the offer() method returns false.

put()

The BlockingQueue put() method inserts the element into the BlockingQueue if it has space for it internally. If the BlockingQueue does not have space for the new element, the put() method will block the thread calling the put() method until the BlockingQueue as space internally for the new element.

take()

The Java BlockingQueue take() method will remove the first element in the BlockingQueue. If the BlockingQueue does not contain any elements, the take() method will block the thread calling take() until an element is inserted into the BlockingQueue.

poll()

The BlockingQueue poll() method will remove the first element in the BlockingQueue. If the BlockingQueue does not contain any elements, the poll() method will return null.

poll(long timeMillis, TimeUnit timeUnit)

The BlockingQueue poll(long timeMillis, TimeUnit timeUnit) method will remove the first element in the BlockingQueue. If the BlockingQueue does not contain any elements, this version of the poll() method will wait for an element to become available for the given amount of time passed to it as parameter. If no element becomes available within the given time out period, this method returns null.

remove(Object o)

The BlockingQueue remove(Object o) method will remove a single instance of the given element from the lockingQueue, if that element exists in the BlockingQueue. The remove() method will use the o.equals(element) to decide if the object o passed as parameter matches a given element in the BlockingQueue. If the BlockingQueue contains more than one element matching the given o parameter, only one of these elements will be removed from the BlockingQueue. The remove() method will return true if an element was removed, and false if not.

peek()

The BlockingQueue peek() method will return the first element of the BlockingQueue without removing it. If the BlockingQueue does not contain any elements, the peek() method will return null.

element()

The BlockingQueue element() method will return the first element of the BlockingQueue without removing it. If the BlockingQueue does not contain any elements, the element() method will throw a NoSuchElementException.

contains(Object o)

The BlockingQueue contains(Object o) method will return true if the BlockingQueue contains an object matching the object passed as parameter to the contains() method. The Objects.equals(o, element) statement is used to check if the parameter object o matches a given element in the BlockingQueue. If an element is found matching the parameter object, this method returns true. If no matching element is found, false is returned.

drainTo(Collection dest)

The drainTo(Collection dest) method drains all the elements of the BlockingQueue into the given destination Collection.

drainTo(Collection dest, int maxElements)

The drainTo(Collection dest, int maxElements) drains up to maxElements from the BlockingQueue into the destination Collection.

size()

The BlockingQueue size() method returns the number of elements stored in BlockingQueue.

remainingCapacity

The BlockingQueue remainingCapacity() method returns the remaining (unused) capacity of the BlockingQueue. The remaining capacity is calculated as full capacity minus the number of elements stored in the BlockingQueue.

Jakob Jenkov

Featured Videos

Java ForkJoinPool

P2P Networks Introduction




















Advertisements

High-Performance
Java Persistence
Close TOC
All Tutorial Trails
All Trails
Table of contents (TOC) for this tutorial trail
Trail TOC
Table of contents (TOC) for this tutorial
Page TOC
Previous tutorial in this tutorial trail
Previous
Next tutorial in this tutorial trail
Next