From the school to A factory all the way sunshine vicissitudes of life

Please go to www.codercc.com


1. BlockingQueue profile

In practical programming, we often use the various container classes in the JDK’s Collection framework, such as those that implement the List,Map, and Queue interfaces. However, these container classes are basically not thread-safe, except that Collections can be converted into thread-safe containers. Doug Lea has prepared thread-safe containers for all of us, such as CopyOnWriteArrayList, which implements the List interface. Implement ConcurrentHashMap for the Map interface (see this article for ConcurrentHashMap), ConcurrentLinkedQueue implements the Queue interface (see this article for ConcurrentLinkedQueue).

The most commonly used “producers – consumers” problem, the queue is often seen as operating data containers, between threads in this way, the business function of each module can be decoupled, producers will “production” of data placed in the container, and consumers only need to access data in the data “container”, This allows the producer and consumer threads to be decoupled and to focus only on their business functions. Blockingqueues are widely used in producer-consumer problems because they provide blocking methods for insertion and removal. When the queue container is full, the producer thread blocks until the queue is full. When the queue container is empty, the consumer thread is blocked until the queue is not empty.

2. Basic operations

The basic actions of BlockingQueue are summarized as follows (this figure is from the JAVA API documentation) :

BlockingQueue Basic operation. PNG

BlockingQueue inherits from the Queue interface, so the basic operations on data elements are:

Insert elements

  1. Add (E E) : Inserts data into the queue. When the queue is full, insert elements and throw an IllegalStateException.
  2. Offer (E E) : When data is inserted into the queue, the message is returned with successtrueOtherwise, returnfalse. No exception is thrown when the queue is full;

Remove elements

  1. Remove (Object O) : deletes data from the queuetrue, or forfalse
  2. Poll: Deletes data. Null is returned when the queue is empty.

Check the elements

  1. Element: Gets the queue head element and throws NoSuchElementException if the queue is empty.
  2. Peek: Gets the header element and throws NoSuchElementException if the queue is empty

Special actions BlockingQueue has:

Insert data:

  1. Put: When the blocking queue capacity is full, the thread that inserts data into the blocking queue will be blocked until the blocking queue capacity is available.
  2. Offer (E E, long timeout, TimeUnit unit) : If the block queue is full, the insertion thread will be blocked until the block queue is empty. Unlike the PUT method, this method has a timeout period. If the timeout period exceeds the specified timeout period, the insertion thread will exit.

Delete the data

  1. Take () : When the blocking queue is empty, the thread fetching queue header data is blocked;
  2. Poll (long timeout, TimeUnit Unit) : When the blocking queue is empty, the thread that fetched the data is blocked. In addition, if the blocked thread exceeds a given length of time, the thread exits

3. Common BlockingQueue

Implements the BlockingQueue interface ArrayBlockingQueue, DelayQueue, LinkedBlockingDeque, LinkedBlockingQueue, LinkedTransferQueue, SynchronousQueue PriorityBlockingQueue SynchronousQueue SynchronousQueue PriorityBlockingQueue SynchronousQueue SynchronousQueue

1.ArrayBlockingQueue

ArrayBlockingQueue is a bounded blocking queue implemented by arrays. The queue commands the element FIFO (first in, first out). Thus, the head element is the oldest data element in the queue, while the mantissa data is the most recent data element in the current queue. ArrayBlockingQueue acts as a “bounded data buffer,” with producers inserting data into the queue container and consumers retrieving it. Once created, ArrayBlockingQueue cannot change its capacity.

When the queue is full, trying to queue elements will block the operation; Trying to fetch an element from an empty queue blocks as well.

ArrayBlockingQueue does not guarantee fairness of thread access to the queue by default. Fairness is defined as the absolute time order in which threads wait, i.e. the thread that waits first is the first to access ArrayBlockingQueue. Non-fairness means that the order in which an ArrayBlockingQueue is accessed is not in strict chronological order, and it is possible that a thread that has blocked for a long time will not be able to access the ArrayBlockingQueue once it is accessible. If fairness is guaranteed, throughput is usually reduced. To get a fair ArrayBlockingQueue, use the following code:

private static ArrayBlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<Integer>(10,true);
Copy the code

For details on how ArrayBlockingQueue works, see this article.

2.LinkedBlockingQueue

LinkedBlockingQueue is a LinkedBlockingQueue that uses a linked list to implement a bounded blocking queue. It also meets FIFO characteristics and has a higher throughput than ArrayBlockingQueue. In order to prevent LinkedBlockingQueue from rapidly increasing in capacity and consuming a large amount of memory. The size of the LinkedBlockingQueue object is usually specified when it is created, and if not, the size is equal to integer.max_value

3.PriorityBlockingQueue

PriorityBlockingQueue is an unbounded blocking queue that supports a priority. Elements are sorted in natural order by default, or they can be specified by implementing the compareTo() method of a custom class, or by using the constructor parameter Comparator when initialized.

4.SynchronousQueue

SynchronousQueue must wait for another thread to delete each insert. Therefore, SynchronousQueue does not actually store any data elements because other threads can insert data only when a thread is deleting. Similarly, if a thread is currently inserting data, The thread can delete the data. SynchronousQueue can also be assigned fairness via constructor arguments.

5.LinkedTransferQueue

LinkedTransferQueue is an unbounded blocking queue composed of linked list data structures. Since this queue implements the TransferQueue interface, it has the following different methods compared with other blocking queues:

Transfer (E) If a thread (consumer) is currently consuming data by calling take() or a delayable poll() method, the producer thread can call transfer to transfer the data to the consumer thread. If there is no consumer thread, the producer thread inserts data to the end of the queue until a consumer can consume it.

TryTransfer (E E) The tryTransfer method can immediately transfer data to the consumer thread if a consumer thread (calling the take method or polling method with timeout) is currently consuming data. If no consumer thread is currently consuming data, Immediately return false. Therefore, in contrast to the Transfer method, the producer thread cannot return until data is consumed by a consumer thread. The tryTransfer method returns results immediately and exits.

TryTransfer (E E, Long timeout,imeUnit unit) is the same as the basic function of Transfer, but with the addition of timeout feature, if the data is not consumed by consumers within the specified timeout time, it will return false.

6.LinkedBlockingDeque

LinkedBlockingDeque is a bounded blocking double-ended queue based on a linked list data structure that defaults to integer-max_value if the size is specified when the object is created. The main difference compared to LinkedBlockingQueue is that LinkedBlockingDeque has the nature of a two-ended queue. The basic action of LinkedBlockingDeque is shown below (from Java documentation)

LinkedBlockingDeque basic operation. PNG

As shown above, the basic actions of LinkedBlockingDeque can be divided into four types: 1. Special case, throw an exception; 2. In special cases, return a special value such as null or false. 3. If the operation condition is not met, the thread is blocked until the condition is met. 4. The operation has the timeout feature.

In addition, LinkedBlockingDeque implements the BlockingDueue interface while LinkedBlockingQueue implements the BlockingQueue interface. The main differences between the two interfaces are shown below (from the Java documentation) :

The difference between BlockingQueue and BlockingDeque. PNG

As you can see from the above figure, the functions of the two interfaces are equivalent. For example, the add method of BlockingQueue is the same as the addLast method of BlockingDeque.

7.DelayQueue

DelayQueue is an unbounded blocking queue that holds Delayed interface data that can only be inserted into the queue for storage when the Delayed time has been reached. If none of the current data has reached the delay period specified when it was created, the queue has no queue head, and null is returned if the thread obtains the data element using methods such as poll. When the Delayed data expires, it is determined by the getDelay(timeunit.nanoseconds) of the Delayed interface. If it returns less than or equal to 0, it means that the Delayed data element has been Delayed.