"Java Multithreading" (8)---blocking queues

Source: Internet
Author: User

blocking queues

Before I write a blocking queue, I wrote a blog about the queue collection, which is mainly for this article.

URL: "Java improvement"---queue collection in this blog, the queues we contact are non-blocking queues, such as Priorityqueue, LinkedList (LinkedList is a doubly linked list, which implements the Dequeue interface).

One big problem with non-blocking queues is that it does not block the current thread, so it is cumbersome to implement additional synchronization policies and inter-thread wake-up policies in the face of similar consumer-producer models.

I. Understanding Blockingqueue

A blocking queue, as the name implies, is first a queue, and a queue plays a role in the data structure roughly as shown:

From what we can clearly see, through a Shared queue, you can make the data input from one end of the queue, and output from the other end;

There are two main types of queues commonly used:

  FIFO: The elements of the first inserted queue are also first out of the queue, similar to the queued functionality. To some extent, this kind of queue also embodies a kind of fairness.

  Last in, first Out (LIFO): The element that is inserted into the queue is first out of the queue, and this queue takes precedence over the most recent occurrence.

Blocking queues are often used by producer and consumer scenarios where producer threads can store production results in a blocking queue, while consumer threads take intermediate results out and modify them in the future.

The queue automatically balances the load, and if the producer thread set runs threads slower than the consumer line, the consumer line threads blocks while waiting for the result, and if the producer thread set runs fast, it waits for the consumer thread set to catch up.

As a blockingqueue user, we no longer need to care about when we need to block threads and when to wake up threads, because all of this blockingqueue you handedly.

Look at the core method of Blockingqueue.

1, put the data

(1)put (e):p ut method is used to deposit elements to the end of the queue, and if the queues are full, wait.

(2)offer (E O, long timeout, timeunit unit): Method used to deposit elements to the end of the team, if the queue is full, then wait a certain amount of time, when the time limit is reached, if not inserted successfully, then return false ; otherwise returns true;

2. Access to Data

(1) Take(): Takes the first element from the team, and waits if the queue is empty;

(2)Drainto(): Get all available data objects from Blockingqueue at once (you can also specify the number of data to get), this method can improve the efficiency of data acquisition, and do not need to lock or release locks multiple times in batches.

(3)poll(time): Take the Blockingqueue in the first row of the object, if not immediately remove, you can wait for the times specified in the parameters, and return null when not taken;

(4)poll(long timeout, timeunit unit): The poll method is used to take elements from the first team, if the queue is empty, it waits for a certain amount of time, when the time period is reached, returns NULL if it is taken, otherwise returns the acquired element;

second, common Blockingqueue

After understanding the basic functions of blockingqueue, let's take a look at the Blockingqueue family members.

1, Arrayblockingqueue

A blocking queue based on an array implementation that must be sized to create a Arrayblockingqueue object . It is also possible to specify fairness and unfairness, which by default is unfair, that is, queues that do not guarantee the longest waiting time have the highest priority to access the queue.

2, Linkedblockingqueue

A blocking queue based on a linked list that, if no capacity size is specified when creating a Linkedblockingqueue object, the default size is Integer.max_value.

3, Priorityblockingqueue

The above 2 queues are FIFO, and priorityblockingqueue is not, it sorts the elements according to the priority of the elements, in order of priority out of the team, each time the element is the highest priority element. Note that this blocking queue is an unbounded blocking queue, which is

Capacity has no upper limit (through the source can be known, it does not have a container full of signal signs), the first 2 kinds are bounded queue.

4, Delayqueue

Based on Priorityqueue, a delay-blocking queue in which elements in the delayqueue can be fetched from the queue only if their specified delay time is reached. Delayqueue is also an unbounded queue, so the operation to insert data into the queue (producer) never

is blocked, and only the operation (consumer) that gets the data is blocked.

5. Small Case

About the producer-consumer, the previous blog I wrote about wait-and-Notifyall implementations, also based on await and signal implementations, URL: https://www.cnblogs.com/qdhxhz/p/9206076.html

This is already a small case of the third related production consumer.

The production consumption model is realized through Linkedblockingqueue.

(1) Test class

 Public classBlockingqueuetest { Public Static voidMain (string[] args)throwsinterruptedexception {//declaring a cache queue with a capacity of 10blockingqueue<string> queue =NewLinkedblockingqueue<string> (10); //new two producers and one consumer, and they share a queue cache queuesProducer Producer1 =NewProducer (queue); Producer Producer2=NewProducer (queue); Consumer Consumer=NewConsumer (queue); //To start a thread through the thread poolExecutorservice Service =Executors.newcachedthreadpool ();             Service.execute (Producer1);                       Service.execute (PRODUCER2);                   Service.execute (consumer); //Perform 5sThread.Sleep (5 * 1000);             Producer1.stop ();                        Producer2.stop (); Thread.Sleep (2000); //Exit ExecutorService.shutdown (); }     }

(2) Producers

/*** Producer Threads*/  Public classProducerImplementsRunnable {Private volatile BooleanIsRunning =true;//whether the flag is running     PrivateBlockingqueue<string> queue;//Blocking Queues     Private StaticAtomicinteger count =NewAtomicinteger ();//values that are automatically updated//constructor Function      PublicProducer (blockingqueue<string>queue) {          This. Queue =queue; }        Public voidrun () {String data=NULL; System.out.println (Thread.CurrentThread (). GetName ()+ "Start the producer thread!" "); Try {              while(isrunning) {Thread.Sleep (1000); //atomically adds 1 to the current value of Countdata = "" +Count.incrementandget (); System.out.println (Thread.CurrentThread (). GetName ()+ "Put production data:" + Data + "into queue"); //set the wait time of 2s, if more than 2s has not added to return false                 if(!queue.offer (data, 2, Timeunit.seconds)) {System.out.println (Thread.CurrentThread (). GetName ()+ "Put data failed:" +data); }             }         } Catch(interruptedexception e) {e.printstacktrace ();         Thread.CurrentThread (). interrupt (); } finally{System.out.println (Thread.CurrentThread (). GetName ()+ "quit the producer thread!" "); }     }        Public voidStop () {isrunning=false; } }

(3) Consumers

/*** Consumer Thread*/  Public classConsumerImplementsRunnable {PrivateBlockingqueue<string>queue; //constructor Function      PublicConsumer (blockingqueue<string>queue) {          This. Queue =queue; }        Public voidrun () {System.out.println (Thread.CurrentThread (). GetName ( )+ "Start the consumer thread!" "); BooleanIsRunning =true; Try {              while(isrunning) {//when there is data directly from the queue of the first team to take away, no data blocking, in 2s data, take away, more than 2s has no data, return failureString data = Queue.poll (2, Timeunit.seconds); if(NULL!=data) {System.out.println (Thread.CurrentThread (). GetName ()+ "Consuming data:" +data); Thread.Sleep (1000); } Else {                     //more than 2s has no data, that all production lines have been exited, automatically exit the consumer thread. IsRunning =false; }             }         } Catch(interruptedexception e) {e.printstacktrace ();         Thread.CurrentThread (). interrupt (); } finally{System.out.println (Thread.CurrentThread (). GetName ()+ "Exit the consumer thread!" "); }     }      }

Run results (one of them)

Third, the implementation of the blocking queue principle

See the implementation of two key methods: put () and take ()

1. Put method
 Public voidPut (e e)throwsinterruptedexception {//The first thing you can see is that you can't put null, no in the report null pointer exception    if(E = =NULL)Throw NewNullPointerException (); Finale[] Items = This. Items; //found using lock lock    FinalReentrantlock lock = This. Lock; //throws an exception if the current thread cannot acquire a locklock.lockinterruptibly (); Try {        Try {             while(Count = =items.length)//This is the key, and we find that the blockage is actually achieved through await () and signal ( ).notfull.await (); } Catch(Interruptedexception IE) {notfull.signal (); Throwie;    } insert (e); } finally{lock.unlock (); }}

When awakened by another thread, insert the element through the Insert (e) method and finally unlock it.

Let's take a look at the implementation of the Insert method:

Private void Insert (E x) {    = x;     = Inc (PUTINDEX);     + +count;    Notempty.signal ();}

It is a private method that, after the insert succeeds, wakes the thread that is waiting to fetch the element through Notempty.

2. Take () method
 PublicE Take ()throwsinterruptedexception {FinalReentrantlock lock = This. Lock;    Lock.lockinterruptibly (); Try {        Try {             while(count = = 0) notempty.await (); } Catch(Interruptedexception IE) {notempty.signal (); Throwie; } E x=extract (); returnx; } finally{lock.unlock (); }}

Similar to the Put method implementation, except that the put method waits for the notfull signal, and the take method waits for the notempty signal. In the Take method, if the element can be taken, the element is obtained through the Extract method,

Here is the implementation of the Extract method:

Private E Extract () {    finalthis. Items;     = Items[takeindex];     NULL ;     = Inc (TAKEINDEX);     --count;    Notfull.signal ();     return x;}

It is similar to the Insert method.

In fact, from here we should understand the implementation of the blocking queue principle, the fact that it and we use object.wait (), object.notify () and non-blocking queue implementation of the producer-consumer thinking similar, but it here through the await () and signal () Implemented together in a blocking queue.

think too much, do too little, the middle of the gap is trouble. Want to have no trouble, either don't think, or do more. Major, "15."

"Java Multithreading" (8)---blocking queues

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.