35 Differences of Blocking Queue Common Methods Add, Offer, Put, Etc

35 Differences of Blocking Queue Common Methods add, offer, put, etc #

In this lesson, we will mainly discuss the common methods in a BlockingQueue and the differences between the add, offer, and put methods.

There are many methods in a BlockingQueue, and they are all very similar. Therefore, it is necessary to distinguish these similar methods. In this lesson, we will classify and clarify the common methods in a BlockingQueue.

We will list the 8 most commonly used methods in the BlockingQueue and divide them into three groups, each group related to adding and removing elements.

These three groups of methods are easily confused because their functionalities are very similar. The only difference lies in the handling of special situations: when the queue is full and cannot add elements, or when the queue is empty and cannot remove elements, the methods in different groups will handle these special situations differently:

  1. Throw exception: add, remove, element
  2. Return result without throwing an exception: offer, poll, peek
  3. Block: put, take

Group 1: add, remove, element #

add method #

The add method is used to add an element to the queue. If the queue is already full, it will throw an exception to indicate that the queue is full. Here is an example code:

private static void addTest() {

    BlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<Integer>(2);

    blockingQueue.add(1);

    blockingQueue.add(1);

    blockingQueue.add(1);

}

In this code, we create a BlockingQueue with a capacity of 2 and try to add 3 values to it. Since it exceeds the capacity limit, an exception will be thrown when adding the third value:

Exception in thread "main" java.lang.IllegalStateException: Queue full

remove method #

The remove method is used to remove an element. If the queue is empty and there are no elements inside, it will throw an exception because there is nothing to remove. Here is an example code:

private static void removeTest() {

    ArrayBlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<Integer>(2);

    blockingQueue.add(1);

    blockingQueue.add(1);

    blockingQueue.remove();

    blockingQueue.remove();

    blockingQueue.remove();

}

In this code, we add 2 elements to a BlockingQueue with a capacity of 2, and then remove 3 elements. Removing the first two elements will be executed normally because there are still elements remaining, but when removing the third element, an exception will be thrown because the queue is already empty.

Exception in thread "main" java.util.NoSuchElementException

element method #

The element method returns the head node of the queue without removing it. Similar to the remove method, if we use this method to operate on an empty queue in order to get the head node, an exception, NoSuchElementException, will be thrown because there is nothing to retrieve. Here is an example code:

private static void elementTest() {

    ArrayBlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<Integer>(2);

    blockingQueue.element();

}

We create a new ArrayBlockingQueue with a capacity of 2 and directly call the element method. Since no elements have been added before, the queue is empty and an exception will be thrown:

Exception in thread "main" java.util.NoSuchElementException

Group 2: offer, poll, peek #

In practice, we usually prefer the methods in Group 2 because they do not throw exceptions like the methods in Group 1. The methods in Group 2 are more user-friendly. When the queue is full and cannot add elements, or when the queue is empty and cannot remove elements, the methods in Group 2 provide a feedback instead of throwing an exception.

offer method #

The offer method is used to insert an element and returns a value to indicate whether the insertion is successful. If the addition is successful, it will return true. If the queue is already full and an offer method is called again, it will not throw an exception but simply return false to indicate an error. Here is an example code:

private static void offerTest() {

    ArrayBlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<Integer>(2);

    System.out.println(blockingQueue.offer(1));

    System.out.println(blockingQueue.offer(1));

    System.out.println(blockingQueue.offer(1));

}

We create an ArrayBlockingQueue with a capacity of 2, and call the offer method three times to attempt to add elements. Each time, the return value is printed. The result is as follows:

true

true

false

It can be seen that the first two additions were successful, but when the third addition was made, the queue had reached its maximum capacity, so it returned false, indicating that the addition failed.

poll method #

The poll method is counterpart to the remove method in the first group. Its purpose is to remove and return the head of the queue. But if the queue is empty and there is nothing to remove, it will return null as a prompt. Therefore, we are not allowed to insert null into the queue, otherwise we cannot distinguish whether the returned null is a prompt or an actual element. The example code is as follows:

private static void pollTest() {

    ArrayBlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<Integer>(3);

    blockingQueue.offer(1);

    blockingQueue.offer(2);

    blockingQueue.offer(3);

    System.out.println(blockingQueue.poll());

    System.out.println(blockingQueue.poll());

    System.out.println(blockingQueue.poll());

    System.out.println(blockingQueue.poll());

}

In this code, we create an ArrayBlockingQueue with a capacity of 3, and add 3 elements to it first. Then we call the poll method four times, and the result is as follows:

1

2

3

null

The first three polls were successful and returned the elements 1, 2, and 3 in the order they were added. The fourth poll method returns null, indicating that there are no more elements to remove at this point.

peek method #

The peek method is counterpart to the element method in the first group. It returns the head element of the queue without removing it. If the queue is empty, it will return null as a prompt. The example code is as follows:

private static void peekTest() {

    ArrayBlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<Integer>(2);

    System.out.println(blockingQueue.peek());

}

The result is:

null

We create an empty ArrayBlockingQueue and directly call peek, which returns null, indicating that there is nothing to retrieve at this point.

offer and poll with timeout #

The second group also includes some additional features worth explaining: offer and poll methods with timeout.

offer(E e, long timeout, TimeUnit unit)

It has three parameters: element, timeout duration, and time unit. Normally, this method will succeed and return true if the insertion is successful. If the queue is full and the insertion fails, when calling the offer method with a timeout, it will wait for the specified timeout duration. If the timeout expires and the insertion still fails, it will return false.

poll(long timeout, TimeUnit unit)

The poll method with timeout parameter is similar to offer. If it can be removed, it will return the content of this node immediately. If the queue is empty, it will wait until the specified timeout expires. If there are still no elements in the queue to be removed, it will return null as a prompt.

Group 3: put and take #

The third group is the familiar put and take methods, the main feature of a blocking queue. Let’s review the explanation of put and take methods in Lesson 34.

put method #

The put method is used to insert elements. Normally, when the queue is not full, the insertion is normal. But if the queue is already full and cannot be inserted, it will not immediately return false or throw an exception. Instead, it will block the inserting thread until there is free space in the queue. At this point, the queue will unblock the previously blocked thread and add the element that was to be inserted.

img

take method #

The take method is used to retrieve and remove the head of the queue. Normally, when there are data in the queue, it will retrieve the data and delete it. But if there is no data in the queue at the time of execution, it will block and wait until there is data in the queue. Once there is data in the queue, it will unblock immediately and retrieve the data.

img

Summary #

This concludes the content of this lesson. In this lesson, we explained the common methods of blocking queues and divided them into three groups, each with its own characteristics. The first group has the characteristic of throwing an exception when unable to execute normally; the second group has the characteristic of not throwing an exception when unable to execute normally, but providing a return value to indicate failure; the third group has the characteristic of blocking the thread when encountering special circumstances, waiting until it can continue execution.

We summarize the 8 methods in the table below:

img With this table, we can clearly understand the relationships between these 8 methods, and you can compare the table carefully after class to deepen your understanding.