boolean offer(E e, long timeout, TimeUnit unit) // insert e, waiting up to the timeout void put(E e) // add e, waiting as long as necessary
E poll(long timeout, TimeUnit unit)
// retrieve and remove the head, waiting up to the timeout
E take() // retrieve and remove the head of this queue, waiting
// as long as necessary
int drainTo(Collection<? super E> c) // clear the queue into c int drainTo(Collection<? super E> c, int maxElements) // clear at most the specified number of elements into c int remainingCapacity() // return the number of elements that would be accepted // without blocking, or Integer.MAX_VALUE if unbounded
But this guarantee doesn't extend to the bulk operations inherited from CollectionaddAll, containsAll, retainAll and removeAllunless the individual implementation provides it. So it is possible, for example, for addAll to fail, throwing an exception, after adding only some of the elements in a collection.
Blocking queue has the following characteristics:
- methods to add an item to the queue, waiting for space to become available in the queue if necessary;
- corresponding methods that take an item from the queue, waiting for an item to put in the queue if it is empty;
- optional time limits and interruptibility on the latter calls;
- efficient thread-safety: blocking queues are specifically designed to have their put() method called from one thread and the take() method from another— in particular, items posted to the queue will be published correctly to any other thread taking the item from the queue again; significantly, the implementations generally achieve this without locking the entire queue, making them highly concurrent components;
- integration with Java thread pools: a flavour of blocking queue can be passed into the constructor of ThreadPoolExecutor to customise the behaviour of the thread pool.
ArrayBlockingQueue : A simple bounded BloickingQueue implementation backed by an array.
DelayQueue : An unbounded blocking queue of Delayed elements, in which an element can only be taken when its delay has expired.It uses elements that implement the new java.util.concurrent.Delayed interface.
PriorityBlockingQueue : This queue bases ordering on a specified Comparator, and the element returned by any take( ) call is the smallest element based on this ordering.
LinkedBlockingQueue : A simple bounded BloickingQueue implementation backed by a linked list.
SynchronousQueue : This queue has a size of zero (yes, you read that correctly). It blocks put( ) calls until another thread calls take( ), and blocks take( ) calls until another thread calls put( ). Essentially, elements can only go directly from a producer to a consumer, and nothing is stored in the queue itself (other than for transition purposes).
Example - Producer consumer problem with Blocking queue
The queue takes care of all the details of synchronizing access to its contents and notifying other threads of the availability of data.
Producer.java
public class Producer extends Thread { private BlockingQueue cubbyhole; private int number; public Producer(BlockingQueue c, int num) { cubbyhole = c; number = num; } public void run() { for (int i = 0; i < 10; i++) { try { cubbyhole.put(i); System.out.format("Producer #%d put: %d%n", number, i); sleep((int)(Math.random() * 100)); } catch (InterruptedException e) { } } } }
Consumer.java
import java.util.concurrent.*; public class Consumer extends Thread { private BlockingQueue<Integer> cubbyhole; private int number; public Consumer(BlockingQueue<Integer> c, int num) { cubbyhole = c; number = num; } public void run() { int value = 0; for (int i = 0; i < 10; i++) { try { value = cubbyhole.take(); System.out.format("Consumer #%d got: %d%n", number, value); } catch (InterruptedException e) { } } } }
ProducerConsumerTest.java
public class ProducerConsumerTest { public static void main(String[] args) { ArrayBlockingQueue c = new ArrayBlockingQueue(1); Producer p1 = new Producer(c, 1); Consumer c1 = new Consumer(c, 1); p1.start(); c1.start(); } }
Possible Use cases for BlockingQueue
These features make BlockingQueues useful for cases such as the following:
- a server, where incoming connections are placed on a queue, and a pool of threads picks them up as those threads become free;
- in a variety of parallel processes, where we want to manage or limit resource usage at different stages of the process.