Java Concurrency (Fundamentals)-blocking queues and producer consumer patterns

Source: Internet
Author: User
Tags throw exception

1. Blocking queue

Blockingqueue is a thread-safe queue version, which, from its name, is a queue implementation that supports blocking: when you request data to an empty blockingqueue, it blocks to blockingqueue non-empty When inserting data into a full blockingqueue, the thread is blocked to Blockingqueue pluggable.

The blockingqueue approach occurs in four forms, for operations that cannot be met immediately but may be satisfied at some point in the future, and these four forms are handled differently: the first is to throw an exception, and the second is to return a special value (null or FALSE, depending on the action). The third is to block the current thread indefinitely before the operation succeeds, and the fourth is to block only within a given maximum time limit before giving up. These methods are summarized in the following table:

Throw exception Special values Blocking Timeout
Insert Add (E)

Offer (e)

Put (e) Offer (E, time, unit)
Removed from Remove () Poll () Take () Take (time, unit)
Check Element () Peek ()

Blockingqueue does not accept null elements. Some implementations throw NullPointerException when attempting to add, put, or offer a null element. Null is used as a warning value indicating that the poll operation failed.

The blockingqueue can be of limited capacity. It can have a remainingcapacity at any given time, exceeding this capacity, and cannot put additional elements without blocking. Blockingqueue that do not have any internal capacity constraints always report the remaining capacity of the integer.max_value.

The following types of blocking queue implementations are available in the JDK, respectively:

    • Arrayblockingqueue: A bounded blocking queue consisting of an array structure.
    • Linkedblockingqueue: A bounded blocking queue consisting of a list structure.
    • Priorityblockingqueue: A unbounded blocking queue that supports priority ordering.
    • Delayqueue: An unbounded blocking queue that only takes out data when the delay expires.
    • Synchronousqueue: A blocking queue that does not store elements.

2. Producer Consumer Model

The blocking queue supports the producer-consumer model, which separates the process of "finding what needs to be done" from the "execute work" and putting the work items into a "to-do" list so that they can be processed later rather than immediately after they are found. The producer-consumer model simplifies the development process because he eliminates code dependencies between producer and consumer classes, and it decouples the process of producing data from the process of using data to simplify workload management because the two processes differ in the rate at which data is processed.

In a producer-consumer design based on a blocking queue, when data is generated, the producer puts the data in the queue, and when the consumer prepares to process the data, it gets the data from the queue. Producers do not need to know the identity or number of consumers, or they are not the only producers, but simply put the data in the queue. Similarly, consumers do not need to know who the producer is or where the job comes from. Blockingqueue simplifies the implementation process of producer-consumer design, which supports any number of producers and consumers. A common producer-consumer design pattern is the combination of a thread pool and a work queue, which is reflected in the Executor task execution framework.

The blocking queue simplifies the coding of the producer-consumer pattern because the take operation blocks until there is data available, and if the producer does not produce work items as soon as possible to keep the consumer busy, then the consumer can only wait until there is work to do. Similarly, a put operation simplifies coding, and if a blocking queue is used, the producer will block and not continue to work when the queue is filled, so that consumers have time to catch up with the producer's speed.

3. Desktop Search Example

There is a type of program that is suitable for decomposition into producers and consumers, such as agents, which scan files on local drives and resume indexing for subsequent searches, similar to some desktop search programs. In the following code, a producer task is given in Crawlerthread, which is to search for files in a file hierarchy that conform to the index criteria and put their names in the work queue. A consumer task is given in Indexerthread, which is to remove the file names from the queue and index them.

The example comes from the Java Concurrency Programming combat.

class Crawlerthread extends Thread {private final blockingqueue<file> Filequeue;private final File root;public crawlerthread (blockingqueue<file> filequeue, File root) {super (); This.filequeue = Filequeue;this.root = root;} public void Run () {try {crawl (root);} catch (Interruptedexception e) {thread.currentthread (). interrupt ();}} private void crawl (File root) throws Interruptedexception {file[] entries = Root.listfiles (); if (entries! = null) {for (Fi Le Entry:entries) {if (Entry.isdirectory ()) crawl (entry); else if (!filequeue.contains (entry)) Filequeue.put (entry);}}} Class Indexerthread extends Thread {private final blockingqueue<file> queue;public Indexerthread (blockingqueue <File> queue) {super (); this.queue = queue;} public void Run () {try {while (true) {Indexfile (Queue.take ())}} catch (Interruptedexception consumed) { Thread.CurrentThread (). interrupt ();}} public void Indexfile (file file) {/* ... */};} 

The producer-consumer model provides a thread-appropriate way to break down desktop search problems into simpler components, decomposing the functions of file traversal and indexing into separate operations, with greater code readability and reusability than putting all of the functionality into one operation: each operation requires only one task to be completed, And the blocking queue will be responsible for all control flows, so the code for each feature is simpler and clearer.

The producer-consumer model can also bring many performance benefits. Producers and consumers can execute concurrently, if one is I/O intensive and one is CPU intensive, then the throughput rate of concurrent execution is higher than the throughput of serial execution. If the degree of parallelism between producers and consumers is different, then coupling them together reduces the overall degree of parallelism to a smaller degree of parallelism.

The following code is used to start multiple search threads with index threads:

public static void Main (string[] args) {final int n_concumers = 10; File[] Roots = ...; blockingqueue<file> queue = new linkedblockingqueue<file> (n); for (File root:roots) New Crawlerthread ( queue, Root). Start (); for (int i = 0; i < n_concumers; i++) new Indexerthread (queue). Start ();

Java Concurrency (Fundamentals)-blocking queues and producer consumer patterns

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.