"Java.util.concurrent package source reading", Linkedblockingqueue

Source: Internet
Author: User

This article is about a slightly more complicated linkedblockingqueue. Linkedblockingqueue is implemented using a list of links, with a head and tail pointing to the beginning of the queue and the end of the queue, respectively. So Linkedblockingqueue will have two locks that control the two elements separately, so that there is no lock conflict when adding elements and removing elements, so taking the element is the head, and adding the element is tail.

First look at the offer method and the poll method

     Public BooleanOffer (e e) {if(E = =NULL)Throw NewNullPointerException (); FinalAtomicinteger count = This. Count; if(Count.get () = =capacity)return false; intc =-1; Node<E> node =NewNode (e); FinalReentrantlock Putlock = This. Putlock;        Putlock.lock (); Try {            if(Count.get () <capacity)                {Enqueue (node); C=count.getandincrement (); if(C + 1 <capacity) notfull.signal (); }        } finally{putlock.unlock (); }        if(c = = 0) Signalnotempty (); returnC >= 0; }

You can see that the offer method only involves putlock when adding elements, but you will still need takelock to see signalnotempty code. And the poll method takes away the element when involves Takelock, also will need putlock. See Signalnotfull (). About Signalnotempty will talk about the blockage later.

     PublicE Poll () {FinalAtomicinteger count = This. Count; if(Count.get () = = 0)            return NULL; E x=NULL; intc =-1; FinalReentrantlock Takelock = This. Takelock;        Takelock.lock (); Try {            if(Count.get () > 0) {x=dequeue (); C=count.getanddecrement (); if(C > 1) notempty.signal (); }        } finally{takelock.unlock (); }        if(c = =capacity) signalnotfull (); returnx; }

Here, by the way, count of the queue length, because there are two locks, so if you still use the basic type of count as Arrayblockingqueue, you will have two locks at the same time, it will be very complex, Therefore, use atomic data type Atomicinteger directly to manipulate count.

Next talk about the problem of blocking, a blockingqueue will have two condition:notfull and Notempty,linkedblockingqueue will have two locks, so these two condition must be created by the two locks, Takelock Create Notempty,putlock Create Notfull.

    /**Lock held by Take, poll, etc*/    Private FinalReentrantlock Takelock =NewReentrantlock (); /**Wait queue for waiting takes*/    Private FinalCondition Notempty =takelock.newcondition (); /**Lock held by put, offer, etc*/    Private FinalReentrantlock Putlock =NewReentrantlock (); /**Wait queue for waiting puts*/    Private FinalCondition notfull = Putlock.newcondition ();

Next look at the put method:

     Public voidPut (e e)throwsinterruptedexception {if(E = =NULL)Throw NewNullPointerException (); //Note:convention in all put/take/etc are to preset local var//holding count negative to indicate failure unless set.        intc =-1; Node<E> node =NewNode (e); FinalReentrantlock Putlock = This. Putlock; FinalAtomicinteger count = This. Count;        Putlock.lockinterruptibly (); Try {            /** Note that count was used in wait guard even though it was * not protected by lock. This works because count can * is decrease at the this point (all other puts is shut * out by Lock) , and we (or some other waiting put) is * signalled if it ever changes from capacity.             similarly * for all and uses of count in other wait guards. */             while(Count.get () = =capacity)            {notfull.await ();            } enqueue (node); C=count.getandincrement (); if(C + 1 <capacity) notfull.signal (); } finally{putlock.unlock (); }        if(c = = 0) Signalnotempty (); }

In fact, the general logic and Arrayblockingqueue almost, will also need to notify the notempty condition, because notempty conditions belong to Takelock, and call signal method need to get lock, So the Put method also uses another lock: Takelock. Here is a bit different, according to the truth, the put method is not required to notify the notfull condition, is by the action of taking the element is notified , but the notfull condition belongs to Putlock, and when the element is taken away, is used Takelock, so here put method in the case of having putlock notify notfull condition , will let other add element method avoid too long wait. Similarly, the Notempty condition is also notified for the Take method.

     PublicE Take ()throwsinterruptedexception {E x; intc =-1; FinalAtomicinteger count = This. Count; FinalReentrantlock Takelock = This. Takelock;        Takelock.lockinterruptibly (); Try {             while(Count.get () = = 0) {notempty.await (); } x=dequeue (); C=count.getanddecrement (); if(C > 1) notempty.signal (); } finally{takelock.unlock (); }        if(c = =capacity) signalnotfull (); returnx; }

Finally, the Remove and contains methods, because the entire list needs to be manipulated, so you need to have a lock to operate.

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.