Java and Contract--linkedblockingdeque

Source: Internet
Author: User
Tags assert int size mutex concurrentmodificationexception

Reprint Please specify source: http://www.cnblogs.com/skywang12345/p/3503480.html

Linkedblockingdeque Introduction

Linkedblockingdeque is a bidirectional concurrent blocking queue implemented by a doubly linked list. The blocking queue supports both FIFO and filo two modes of operation, that is, both the head and tail of the queue can be manipulated (insert/delete), and the blocking queue is support for thread safety.

In addition, the linkedblockingdeque is optional (prevents excessive bloat), that is, the capacity of the queue can be specified. If not specified, the default capacity size is equal to Integer.max_value.

linkedblockingdeque principles and data Structures

Linkedblockingdeque the data structure, as shown in:

Description :
1. Linkedblockingdeque inherits from Abstractqueue, which is essentially a two-way queue that supports FIFO and Filo.
2. Linkedblockingdeque implements the Blockingdeque interface, which supports multithreading concurrency. When multithreading competes for the same resource, a thread acquires the resource, and other threads need to block the wait. The
3. Linkedblockingdeque is implemented through a doubly linked list. The
3.1 first is a table header for a doubly linked list. The
3.2 last is the footer of a doubly linked list. The
3.3 count is the actual size of the Linkedblockingdeque, which is the number of current nodes in the doubly linked list. The
3.4 capacity is the capacity of Linkedblockingdeque, which is specified when the Linkedblockingdeque is created. The
3.5 lock is a mutex that controls Linkedblockingdeque, and when multiple threads compete to access linkedblockingdeque at the same time, a thread acquires the mutex lock and other threads need to block the wait. Until the thread releases lock, other threads have access to lock to gain CPU execution. The
3.6 notempty and notfull are non-null conditions and not full conditions, respectively. They allow for more delicate concurrency control.

     --If a thread (thread a) is about to take out the data, the queue is exactly empty, and the thread executes notempty.await () to wait, and when another thread (thread B) inserts data into the queue, it calls Notempty.signal () wake Up " Wait thread on the Notempty ". At this point, thread A will be woken up to continue running. In addition, thread A acquires Takelock before the fetch operation is performed, and then releases Takelock after the fetch operation has been completed.     --If the queue is full when a thread (thread h) is about to insert data, the thread will wait for it to execute notfull.await (), and when another thread (thread i) takes out the data, it calls Notfull.signal () to wake up the wait thread on Notfull ”。 At this point, thread H is awakened to continue running. In addition, thread H acquires Putlock before the insert operation, releasing Putlock when the insert operation is complete.

For more information about Reentrantlock and condition, refer to:
Java Multithreading Series--"Juc lock" 02 of mutual exclusion lock Reentrantlock
() Java Multithreading Series--"Juc lock" 03 Fair Lock (One)
Java Multithreading Series--"Juc lock" 04 Fair Lock (II)
Java Multithreading Series--"Juc lock" 05 's Unfair lock
Java Multithreading Series--"Juc lock" 06 of the condition conditions

List of Linkedblockingdeque functions
Create a linkedblockingdeque with a capacity of integer.max_value. Linkedblockingdeque ()//Creates a linkedblockingdeque with a capacity of integer.max_value, initially containing the elements of the given collection, added in the order in which the collection iterator is traversed. Linkedblockingdeque (collection<? extends e> c)//Create a linkedblockingdeque with a given (fixed) capacity. Linkedblockingdeque (int capacity)//The specified element is inserted at the end of this double-ended queue without violating the capacity limit. Boolean Add (E)//if it is immediately feasible and does not violate the capacity limit, the specified element is inserted at the beginning of this double-ended queue, and illegalstateexception is thrown if there is currently no space available. void AddFirst (e e)//if it is immediately feasible and does not violate the capacity limit, the specified element is inserted at the end of this double-ended queue, and illegalstateexception is thrown if there is currently no space available. void AddLast (e e)//in atomic mode (atomically) removes all elements from this double-ended queue. void clear ()//Returns True if this double-ended queue contains the specified element. Boolean contains (Object O)//Returns an iterator that iterates through the elements of this double-ended queue in reverse sequential order. Iterator<e> descendingiterator ()//Remove all the available elements from this queue and add them to the given collection. int Drainto (COLLECTION&LT;? super e> C)//To remove a given number of available elements from this queue and add them to a given Collection. int Drainto (COLLECTION&LT;? super e> C, int maxelements)//Gets but does not remove the head of the queue represented by this double-ended queue. E element ()//gets, but does not remove the first element of this double-ended queue. E GetFirst ()//gets, but does not remove the last element of this double-ended queue. E getlast ()//return this double-ended queue element with the appropriateAn iterator that iterates sequentially. Iterator<e> Iterator ()//if it is immediately feasible and does not violate the capacity limit, the specified element is inserted into the queue represented by this double-ended queue (that is, the tail of this double-ended queue) and returns true on success, or False if no space is currently available. Boolean offer (E)//inserts the specified element into the queue represented by this double-ended queue (that is, the tail of this double-ended queue) and, if necessary, waits for free space within the specified wait time. Boolean offer (e E, long timeout, timeunit unit)//if it is immediately feasible and does not violate the capacity limit, the specified element is inserted at the beginning of this double-ended queue, and returns true on success, or False if no space is currently available. Boolean Offerfirst (E)//inserts the specified element at the beginning of this double-ended queue and, if necessary, waits for free space within the specified wait time. Boolean Offerfirst (e E, long timeout, timeunit unit)//if it is immediately feasible and does not violate the capacity limit, the specified element is inserted at the end of this double-ended queue and returns true on success, or if no space is currently available False Boolean offerlast (E)//inserts the specified element at the end of this double-ended queue and, if necessary, waits for free space within the specified wait time. Boolean offerlast (e E, long timeout, timeunit unit)//gets but does not remove the head of the queue represented by this double-ended queue (that is, the first element of this double-ended queue), or null if this double-ended queue is empty. E peek ()//Gets but does not remove the first element of this double-ended queue, or null if this double-ended queue is empty. E Peekfirst ()//gets, but does not remove the last element of this double-ended queue, or null if this double-ended queue is empty. E peeklast ()//Gets and removes the head of the queue represented by this double-ended queue (that is, the first element of this double-ended queue), or null if this double-ended queue is empty. E poll ()//Gets and removes the head of the queue represented by this double-ended queue (that is, the first element of this double-ended queue) and, if necessary, waits for the available elements within the specified wait time. E Poll (long timeout, timeunit unit)//Gets and removes the first element of this double-ended queue, or null if this double-ended queue is empty. E Pollfirst ()//Get and remove thisThe first element of a double-ended queue, which, if necessary, waits for the available elements at the specified wait time. E Pollfirst (long timeout, timeunit unit)//Gets and removes the last element of this double-ended queue, or null if this double-ended queue is empty. E polllast ()//Gets and removes the last element of this double-ended queue and, if necessary, waits for the available elements within the specified wait time. E Polllast (long timeout, timeunit unit)//POPs an element from the stack represented by this double-ended queue. E pop ()//pushes elements into the stack represented by this double-ended queue. void push (E E)//inserts the specified element into the queue represented by this double-ended queue (that is, the tail of this double-ended queue) and waits for free space if necessary. void put (e e)//inserts the specified element at the beginning of this double-ended queue and waits for free space if necessary. void Putfirst (e e)//inserts the specified element at the end of this double-ended queue and waits for free space if necessary. void Putlast (e e)//returns the ideal (no memory and resource constraints) the number of extra elements this double-ended queue can accept without blocking. int remainingcapacity ()//Gets and removes the head of the queue represented by this double-ended queue. E Remove ()//from this double-ended queue removes the first occurrence of the specified element. The Boolean remove (Object O)//Gets and removes the first element of this double-ended queue. E Removefirst ()//from this double-ended queue removes the first occurrence of the specified element. Boolean removefirstoccurrence (Object o)//Gets and removes the last element of this double-ended queue. E removelast ()//The last occurrence of the specified element is removed from this double-ended queue. Boolean removelastoccurrence (Object o)//Returns the number of elements in this double-ended queue. int size ()//Gets and removes the head of the queue represented by this double-ended queue (the first element of this double-ended queue) and waits for the available elements if necessary. E take ()//Gets and removes the first element of this double-ended queue and waits for the available elements if necessary. E Takefirst ()//Gets and removes the last element of this double-ended queue and waits for the available elements if necessary. E takelast ()//Returns an array that contains all elements of this double-ended queue in the appropriate order (from the first element to the last element). Object[] ToArray ()//return to the appropriateThe sequence contains an array of all elements of this double-ended queue; The run-time type of the returned array is the run-time type of the specified array. <T> t[] ToArray (t[] a)//returns the string representation of this collection. String toString ()

linkedblockingdeque Source Analysis (jdk1.7.0_40 version)

Linkedblockingdeque.java's complete source code is as follows:

View Code

The following is an analysis of linkedblockingdeque from the creation, addition, extraction, and traversal of Arrayblockingqueue

1. Create

The following is illustrated with Linkedblockingdeque (int capacity).

public linkedblockingdeque (int capacity) {    if (capacity <= 0) throw new IllegalArgumentException ();    This.capacity = capacity;}

Description : Capacity is the capacity of the "chained blocking queue".


The relevant data results in Linkedblockingdeque are defined as follows:

The header of the two-way queue transient node<e> first;//The footer of the two-way queue transient node<e> last;//The number of nodes private transient int count;// Capacity private final int capacity;//mutex, mutex corresponding to "non-null condition Notempty", mutex corresponding to "not full condition Notfull" final reentrantlock lock = new Reentrantloc K ();p rivate final Condition notempty = lock.newcondition ();p rivate final Condition notfull = Lock.newcondition ();

Description : Lock is a mutex used to control mutually exclusive access to elements in Linkedblockingdeque, while Notempty and notfull are conditions that bind to lock and are used to achieve more precise control over multithreading.

The node nodes of the doubly linked list are defined as follows:

Static Final class Node<e> {    E item;       Data    node<e> prev;//Previous node    node<e> next;//Backend node    (E x) {item = x;}}

2. Add

The following is an example of an offer (e E), which describes how to add a linkedblockingdeque.

Public Boolean offer (E e) {    return offerlast (e);}

The offer () is actually called offerlast () to add the element to the end of the queue.

The source code of Offerlast () is as follows:

public boolean offerlast (E e) {    if (E = = null) throw new NullPointerException ();    New nodes    node<e> node = new node<e> (E);    Final Reentrantlock lock = This.lock;    Get lock    Lock.lock ();    try {        //adds "new node" to the end of the doubly linked list        return linklast (node);    } finally {        //release lock        Lock.unlock ();}    }

Description : The Role of Offerlast () is to create a new node and insert the node at the end of a doubly linked list. It acquires a lock before inserting the node, completes the operation, and then releases the lock.

The source code of Linklast () is as follows:

Private Boolean Linklast (node<e> node) {    //If "number of nodes in the doubly linked list" > "Capacity", then false is returned, indicating that the insert failed.    if (count >= capacity)        return false;    Add "node to the end of the list" and set node to the new tail node    node<e> l = last;    Node.prev = l;    last = node;    if (first = = null) First        = node;    else        l.next = node;    "Number of nodes" +1    ++count;    After inserting the node, wake the waiting thread on the notempty.    notempty.signal ();    return true;}

Description : The Role of Linklast () is to insert a node into the end of a two-way queue; After inserting a node, wake the waiting thread on the notempty.


3. Delete

The following takes take () as an example, the method of extracting Linkedblockingdeque is described.

Public E take () throws Interruptedexception {    return Takefirst ();}

Take () is actually the first element that calls the Takefirst () queue.

The source code of Takefirst () is as follows:

Public E Takefirst () throws Interruptedexception {    final reentrantlock lock = This.lock;    Get lock    Lock.lock ();    try {        E x;        If "Queue is empty", wait all the time. Otherwise, the first node is removed by Unlinkfirst ().        while ((x = Unlinkfirst ()) = = null)            notempty.await ();        return x;    } finally {        //release lock        Lock.unlock ();    }}

Description : The function of Takefirst () is to delete the first node of the doubly linked list and return the value corresponding to the node. It acquires a lock before inserting the node, completes the operation, and then releases the lock.

The source code of Unlinkfirst () is as follows:

Private E Unlinkfirst () {    //Assert Lock.isheldbycurrentthread ();    Node<e> f = First;    if (f = = null)        return null;    Delete and update "first node"    node<e> n = f.next;    E item = F.item;    F.item = null;    F.next = f; Help GC First    = n;    if (n = = null) last        = null;    else        n.prev = null;    "Number of nodes"-1    --count;    After deleting the node, wake the waiting thread on the notfull.    notfull.signal ();    return item;}

Description : The Role of Unlinkfirst () is to remove the first node of the bidirectional queue, and wake the waiting thread on the notfull after the node is deleted.

4. Traverse

The following is a description of the Linkedblockingdeque traversal method.

Public iterator<e> Iterator () {    return new Itr ();}

Iterator () is actually returning a ITER object.

The ITR class is defined as follows:

Private class Itr extends Abstractitr {    //"bidirectional queue" header    node<e> Firstnode () {return first;}    Get "Node n next node"    node<e> NextNode (node<e> N) {return n.next;}}

ITR inherits from Abstractitr, and ABSTRACTITR is defined as follows:

Private abstract class Abstractitr implements Iterator<e> {//Next is the node that the next call to Next () will return.    Node<e> Next;    Nextitem is the data for the next () return node.    E Nextitem;    The node that was last returned by next ().    Private node<e> Lastret;    Returns the first node of the abstract node<e> firstnode ();    Returns the next node, abstract node<e> NextNode (node<e> N);        Abstractitr () {final reentrantlock lock = LinkedBlockingDeque.this.lock;        Get the "Linkedblockingdeque Mutex" lock.lock ();            try {//Get the header of the "bidirectional queue" next = Firstnode (); Gets the data for the header corresponding to Nextitem = (next = null)?        Null:next.item;        } finally {//releases "Linkedblockingdeque Mutex" lock.unlock ();  }}//Gets the successor of N private node<e> succ (node<e> N) {//Chains of deleted nodes ending in null or        Self-links//Is possible if multiple interior nodes is removed. for (;;)            {node<e> s = nextnode (n); If(s = = null) return null;            else if (s.item! = null) return s;            else if (s = = N) return Firstnode ();        else n = s;    }}//Update Next and Nextitem.        void Advance () {final reentrantlock lock = LinkedBlockingDeque.this.lock;        Lock.lock ();            try {//assert next! = NULL;            Next = SUCC (next); Nextitem = (next = null)?        Null:next.item;        } finally {Lock.unlock ();    }}//returns "whether the next node is null" public boolean Hasnext () {return next! = NULL;        }//Returns the next node public E next () {if (next = null) throw new Nosuchelementexception ();        Lastret = Next;        E x = Nextitem;        Advance ();    return x;        }//Delete the next node public void Remove () {node<e> n = lastret;        if (n = = null) throw new IllegalStateException ();        Lastret = null; Final ReentRantlock lock = LinkedBlockingDeque.this.lock;        Lock.lock ();        try {if (N.item! = null) unlink (n);        } finally {Lock.unlock (); }    }}

Linkedblockingdeque Example
 1 Import java.util.*; 2 Import java.util.concurrent.*; 3 4/* 5 * Linkedblockingdeque is a "thread-safe" queue, and LinkedList is non-thread-safe. 6 * 7 * Below is an example of "multiple threads working simultaneously and traversing the queue" 8 * (01) The program works correctly when the queue is a Linkedblockingdeque object. 9 * (02) When the queue is a LinkedList object, the program produces an concurrentmodificationexception exception. *11 * @author skywang12 */13 public class LinkedBlockingDequeDemo1 {//Todo:queue is a LinkedList object, the program will error. //private static queue<string> Queue = new linkedlist<string> (), + private static QUEUE&LT;STRING&G T Queue = new linkedblockingdeque<string> (); public static void Main (string[] args) {19 20//Start both The thread is working on the queue! New MyThread ("Ta"). Start (); New MyThread ("TB"). Start ();}24 private static void Printall () {-String value;27 Iterator iter = Queue.iterator (); while (Iter.hasnext ()) {V Alue = (String) iter.next (), System.out.print (value+ ","),}32 SYstem.out.println ();}34 private static Class MyThread extends Thread {MyThread (String name) {37             Super (name),}39 @Override40 public void Run () {$ int i = 0;42 while (i++ < 6) {43//"Thread name" + "-" + "ordinal", String val = Thread.CurrentThread (). GetName () +i;45 Queue.add (val); 46//Traverse the queue through "Iterator". Printall (); 48}49}50}51}

Run results (one time) :

Ta1, Ta1, TB1, Tb1,ta1, Ta1, TB1, TB1, TB2, TB2, Ta2, Ta2, Ta1, Ta1, TB1, TB1, TB2, TB2, Ta2, Ta2, Tb3, Tb3, TA3, TA3, ta1 , TB1, Ta1, TB2, TB1, Ta2, TB2, Tb3, Ta2, TA3, Tb3, TB4, TA3, TA4, TB4, Ta1, TA4, TB1, Tb5, TB2, Ta1, Ta2, TB1, Tb3, TB2, TA3, Ta2, TB4, Tb3, TA4, TA3, Tb5, TB4, Ta5, TA4, Ta1, Tb5, TB1, Ta5, TB2, Tb6, Ta2, Ta1, Tb3, TB1, TA3, TB2, TB4, Ta2, Ta 4, Tb3, Tb5, TA3, Ta5, TB4, Tb6, TA4, TA6, Tb5, Ta5, Tb6, TA6,

The result description : In the sample program, start two threads (thread TA and thread TB) to operate on the Linkedblockingdeque respectively. In the case of thread ta, it takes "thread name" + "ordinal", then adds the string to Linkedblockingdeque, and then traverses and outputs all the elements in the Linkedblockingdeque. The thread TB operation is the same as thread ta, except that the name of the thread TB differs from the name of the thread ta.
The program works correctly when the queue is a Linkedblockingdeque object. If you change the queue to LinkedList, the program produces an concurrentmodificationexception exception.

Java and contract--linkedblockingdeque

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.