ArrayBlockingQueue

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.

Download
You can download the full source code of this example here : ArrayBlockingQueueExample.rar

Ilias Koutsakis

Ilias has graduated from the Department of Informatics and Telecommunications of the National and Kapodistrian University of Athens. He is interested in all aspects of software engineering, particularly data mining, and loves the challenge of working with new technologies. He is pursuing the dream of clean and readable code on a daily basis.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
vafd
vafd
6 years ago

Here the Consumer thread is not consuming anything from the queue.

Back to top button