java.util.concurrent.ArrayBlockingQueue Example
In this post we are going to present the ArrayBlockingQueue
class, which implements the BlockingQueue
interface. The main reason to use the ArrayBlockingQueue
class is that it is thread-safe, in the sense that it can be used concurrently between different threads without any risk. Moreover, it has a specific capacity limit, which can be used in our advantage, e.g. when we try to add an element and there are no remaining spots for it, we can use the appropriate method to block the insertion until it can be achieved.
1. ArrayBlockingQueue Example
In our example we want to put emphasis into the concurrency capabilities of ArrayBlockingQueue
, as well as the usage of the capacity limit that it imposes. We crated a simple Producer-Consumer situation, where we have a producer trying to add elements in the queue, and a consumer that watches the number of elements, as well as the remaining capacity of the queue. Let’s take a look.
ArrayBlockingQueueExample.java
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; public class ArrayBlockingQueueExample { public static void main(String[] args) { // Let's create a blocking queue that can hold at most 5 elements. BlockingQueue queue = new ArrayBlockingQueue<>(5); // The two threads will access the same queue, in order // to test its blocking capabilities. Thread producer = new Thread(new Producer(queue)); Thread consumer = new Thread(new Consumer(queue)); producer.start(); consumer.start(); } }
Producer.java
import java.util.concurrent.BlockingQueue; public class Producer implements Runnable{ private BlockingQueue queue; public Producer(BlockingQueue queue) { this.queue = queue; } @Override public void run() { // We are adding elements using offer() in order to check if // it actually managed to insert them. for (int i = 0; i < 8; i++) { System.out.println("Trying to add to queue: String " + i + " and the result was " + queue.offer("String " + i)); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } }
Consumer.java
import java.util.concurrent.BlockingQueue; public class Consumer implements Runnable{ private BlockingQueue queue; public Consumer(BlockingQueue queue) { this.queue = queue; } @Override public void run() { // As long as there are empty positions in our array, // we want to check what's going on. while (queue.remainingCapacity() > 0) { System.out.println("Queue size: " + queue.size() + ", remaining capacity: " + queue.remainingCapacity()); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } }
Output
Queue size: 0, remaining capacity: 5 Trying to add to queue: String 0 and the result was true Queue size: 1, remaining capacity: 4 Trying to add to queue: String 1 and the result was true Queue size: 2, remaining capacity: 3 Trying to add to queue: String 2 and the result was true Queue size: 3, remaining capacity: 2 Trying to add to queue: String 3 and the result was true Queue size: 4, remaining capacity: 1 Trying to add to queue: String 4 and the result was true Trying to add to queue: String 5 and the result was false Trying to add to queue: String 6 and the result was false Trying to add to queue: String 7 and the result was false
So, what is happening here? We have created 2 separate threads that both have access to the same ArrayBlockingQueue
(of size 5). The Producer thread tries to add elements to the queue, and checks if the insertion was successful. On the other hand, the Consumer thread checks the state of the queue (whether it is full or not) and continues to check until the queue is full, where it exits. If you take a look at the output, you can clearly see that the last 3 insertions failed, which is expected, as the queue had an immutable size of 5.
So, what we can clearly see here is:
- The
ArrayBlockingQueue
has a fixed size. - It is thread-safe, and by using the right methods we can easily avoid exceptions.
There is a variety of methods that can be used in an ArrayBlockingQueue
, most of which are shared between similar interfaces (that use Queue
implementations).
2. Download the example
This was an example of ArrayBlockingQueue.
You can download the full source code of this example here : ArrayBlockingQueueExample.rar
Here the Consumer thread is not consuming anything from the queue.