cool hit counter concrrent class under BlockingDeque write your own implementation code_Intefrankly

concrrent class under BlockingDeque write your own implementation code


I. Introduction to LinkedBlockingDeque

   java6 added two container types, Deque and BlockingDeque, which extend Queue and BlockingQueue respectively. Dequeis a double-ended queue,deque( double-ended queue) be "Double Ended Queue" of abbreviated。 therefore, A double-ended queue is a queue that you can start from either end insertion Or extracting elements of formation。 implements a queue head and queue tail at the of efficient insertion harmony remove。    The BlockingDeque class is a double-ended queue that blocks the thread attempting to insert an element when it cannot be inserted, and blocks the thread attempting to extract an element when it cannot be extracted.

   just as blockage Queue Usage and Producers- Consumer Model,

The same applies to the double-ended queue for another related pattern, namely work permitting。 In the producer- In Consumer Design, All consumers have a shared of work queue, and in work permitting in design, Each consumer has their own of double-ended queue。 If a consumer completes its own double-ended queue of of All work, Then it can secretly get work from other consumers at the end of the double-ended queue。 The secret working mode is more than the traditional of manufacturer- The consumer model has a higher of scalability, This is because worker threads don't work on a single shared of Competition occurs on the task queue。 in most instances, They all just visit themselves of double-ended queue, thereby significantly reducing competition。 When a worker thread needs to access another queue, It will be taken from the queue of The tail rather than the head gets the job, Thus further reducing the queue on of Level of competition。

LinkedBlockingDeque be bi-directional chain table realize of Two-way concurrency blockage formation。 should blockage The queue also supportsFIFO harmonyFILO Two types of operation, i.e., it is possible to get a queue from the of Head and tail operation at the same time( insertion/ removing); furthermore, should blockage Queues are thread-safe enabled。 In addition, LinkedBlockingDeque is also capacity-selectable (to prevent over-inflation), i.e. the capacity of the queue can be specified. If not specified, the default capacity size is equal to Integer.MAX_VALUE.

Use of BlockingDeque

A thread is both a queue of The producer is again this queue of consumers of When you can use to BlockingDeque。 If the producer thread needs to be in the queue of Both ends are fine. insertion data, Consumer threads need to be in the queue of Both ends are fine. remove data, This time you can also use the BlockingDeque。BlockingDeque diagrams:

an BlockingDeque - Threads in the double-ended queue of Both ends are fine. insertion and extracted elements。 A thread producing elements, And put them insertion go to the queue of any end。 If the double-ended queue is full, insertion The thread will be blockage, Until a remove The thread moves an element out of that queue。 If the double-ended queue is empty, remove The thread will be blockage, Until a insertion threads to that queue insertion There is a new element。

Methods of BlockingDeque

BlockingDeque has 4 different sets of methods for inserting, removing, and checking elements in a double-ended queue. Each method behaves differently if the requested operation cannot be executed immediately. These methods are as follows.

throw an exception

particular value

blockage

timeout

insertion

addFirst(o)

offerFirst(o)

putFirst(o)

offerFirst(o, timeout, timeunit)

remove

removeFirst(o)

pollFirst(o)

takeFirst(o)

pollFirst(timeout, timeunit)

inspections

getFirst(o)

peekFirst(o)

throw an exception

particular value

blockage

timeout

insertion

addLast(o)

offerLast(o)

putLast(o)

offerLast(o, timeout, timeunit)

remove

removeLast(o)

pollLast(o)

takeLast(o)

pollLast(timeout, timeunit)

inspections

getLast(o)

peekLast(o)

Four different sets of behavioural patterns are explained.

  1. throw an exception : Throws an exception if the attempted operation cannot be executed immediately.
  2. particular value : Returns a specific value (often true / false) if the attempted operation cannot be executed immediately.
  3. blockage : If the attempted operation cannot be executed immediately, the method call will block until it can be executed.
  4. timeout: If an attempt is made to of Operation cannot be executed immediately, This method call will occur blockage, Until it can be implemented, But the waiting time will not exceed the given value。 Return a particular value to tell if the operation was successful( typical of be true / false)。

BlockingDeque inherits from BlockingQueue

The BlockingDeque interface inherits from the BlockingQueue interface. This means that you can use a BlockingDeque just as you would a BlockingQueue. If you do this, the various insert methods will add the new element to the end of the double-ended queue, and the remove methods will remove the element at the head of the double-ended queue. Just like the insert and remove methods of the BlockingQueue interface. The following are BlockingDeque's specific internal implementations of the methods of the BlockingQueue interface.

BlockingQueue

BlockingDeque

add()

addLast()

offer() x 2

offerLast() x 2

put()

putLast()

remove()

removeFirst()

poll() x 2

pollFirst()

take()

takeFirst()

element()

getFirst()

peek()

peekFirst()

2、LinkedBlockingDeque Source Code Analysis

2.1、LinkedBlockingDeque oflock

LinkedBlockingDeque of The principle is to use a reentrant lock and this lock to generate of Two conditional objects for concurrency control(classic two-condition algorithm)。LinkedBlockingDeque is a program with a length of blockage formation, initialize of You can specify the queue length when( If not specified it isInteger.MAX_VALUE), and no modification is allowed after the specified length。

    /** Main lock guarding all access */
    final ReentrantLock lock = new ReentrantLock();

    /** Condition for waiting takes */
    private final Condition notEmpty = lock.newCondition();

    /** Condition for waiting puts */
    private final Condition notFull = lock.newCondition();

2.2. Data structure

bi-directional chain table

 /** Two-way linked table nodes */  
 //ava Inside static is generally used to modify member variables or functions. However, one special use is to modify internal classes with static; ordinary classes are not allowed to be declared static, only internal classes are. An inner class modified by static can be used directly as a normal class without instantiating an outer class
 //final means that no other classes are allowed to inherit from this class

static final class Node<E> {  
    /** 
      * elemental value 
     */  
    E item;  
  
    /** 
      * nodal precursor 
      * 1. pointing to a precursor; 2. pointing to this, indicating that the precursor is a tail node, see unlinklast; 3. pointing to null indicating that there is no precursor 
     */  
    Node<E> prev;  
  
    /** 
      * nodal successor 
      * 1. pointing to a successor; 2. pointing to this,indicating that the successor is the head node, see unlinkfirst; 3. pointing to null indicating that there is no successor 
     */  
    Node<E> next;  
  
    Node(E x) {  
        item = x;  
    }  
}  

2.3. Member variables

     //first is the head of a two-way linked table
    transient Node<E> first;  // Serialization is not allowed  Keeping it safe

     //last is the end of a two-way linked table
    transient Node<E> last;

     //count is the actual size of the LinkedBlockingDeque, i.e. the number of current nodes in the bidirectional link table
    private transient int count;

     // is the capacity of the LinkedBlockingDeque, which is specified when the LinkedBlockingDeque is created
    private final int capacity;

2.4. Constructor

    public LinkedBlockingDeque() {
        this(Integer.MAX_VALUE);
    }
    
    public LinkedBlockingDeque(int capacity) {
        if (capacity <= 0) throw new IllegalArgumentException();
        this.capacity = capacity;
    }

    public LinkedBlockingDeque(Collection<? extends E> c) {
        this(Integer.MAX_VALUE);
        final ReentrantLock lock = this.lock;
        lock.lock(); // Never contended, but necessary for visibility
        try {
            for (E e : c) {
                if (e == null)
                    throw new NullPointerException();
                if (!linkLast(new Node<E>(e)))
                    throw new IllegalStateException("Deque full");
            }
        } finally {
            lock.unlock();
        }
    }

2.5. Admission to the team

addFirst, addLast call offerFirst,offerLast respectively, while offerFirst,offerLast and putFirst,putLast both call linkFirst and linkLast.

    public void addFirst(E e) {
        if (!offerFirst(e))
            throw new IllegalStateException("Deque full");
    }
    
    public void addLast(E e) {
        if (!offerLast(e))
            throw new IllegalStateException("Deque full");
    }
    
    public boolean offerFirst(E e) {
        if (e == null) throw new NullPointerException();
        Node<E> node = new Node<E>(e);
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return linkFirst(node);
        } finally {
            lock.unlock();
        }
    }
    
    public boolean offerLast(E e) {
        if (e == null) throw new NullPointerException();
        Node<E> node = new Node<E>(e);
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return linkLast(node);
        } finally {
            lock.unlock();
        }
    }
    
    public void putFirst(E e) throws InterruptedException {
        if (e == null) throw new NullPointerException();
        Node<E> node = new Node<E>(e);
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            while (!linkFirst(node))
                notFull.await();
        } finally {
            lock.unlock();
        }
    }
    
    public void putLast(E e) throws InterruptedException {
        if (e == null) throw new NullPointerException();
        Node<E> node = new Node<E>(e);
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            while (!linkLast(node))
                notFull.await();
        } finally {
            lock.unlock();
        }
    }

linkFirst and linkLast

/** 
  * Set node to the head node of the chain table, false when the chain table is full 
 */  
private boolean linkFirst(Node<E> node) {  
    // assert lock.isHeldByCurrentThread();  
    if (count >= capacity) // Exceeding capacityfalse  
        return false;  
    Node<E> f = first;  
     node.next = f;  //next of the new node points to the original first  
     first = node;  //set node to the new first  
     if (last == null) // no tail node, set node to tail  
        last = node;  
    else  
         f.prev = node;  // with a tail node, then point the previous first's pre to the new node
++count;  //accumulate the number of nodes //I missed it here in the implementation code
     notEmpty.signal();  // Notify non-empty conditional queues when new nodes are added to the queue  
    return true;  
}  
  
/** 
  * Set node to the tail node of the chain table, false when the chain table is full 
 */  
private boolean linkLast(Node<E> node) {  
    // assert lock.isHeldByCurrentThread();  
    if (count >= capacity)  
        return false;  
    Node<E> l = last;  
    node.prev = l;  
    last = node;  
     if (first == null) // is null, that means the previous queue is empty, then first also points to node  
        first = node;  
    else  
         l.next = node;  //Non-null, which means the previous last has a value, points the previous last's next to the node  
    ++count;  
    notEmpty.signal();  
    return true;  
}  

2.6. Out of team

    public E removeFirst() {
        E x = pollFirst();
        if (x == null) throw new NoSuchElementException();
        return x;
    }
    
    public E removeLast() {
        E x = pollLast();
        if (x == null) throw new NoSuchElementException();
        return x;
    }
    
    public E pollFirst() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return unlinkFirst();
        } finally {
            lock.unlock();
        }
    }
    
    public E pollLast() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return unlinkLast();
        } finally {
            lock.unlock();
        }
    }
    
    public E takeFirst() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            E x;
            while ( (x = unlinkFirst()) == null)
                notEmpty.await();
            return x;
        } finally {
            lock.unlock();
        }
    }
    
    public E takeLast() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            E x;
            while ( (x = unlinkLast()) == null)
                notEmpty.await();
            return x;
        } finally {
            lock.unlock();
        }
    }
    

Core Approach

/** 
 *  remove head node, Returning an empty link tablenull 
 */  
private E unlinkFirst() {  
    // assert lock.isHeldByCurrentThread();  
    Node<E> f = first;  
    if (f == null)  
         return null;  //null returns null
    Node<E> n = f.next;  
    E item = f.item;  
    f.item = null;  
    f.next = f; // help GC  
    first = n;  
    if (n == null) // It means that there should be only one node before, remove after the head node, chain table empty, present .first harmonylast all point tonull finish  
        last = null;  
    else  
         n.prev = null;  // Otherwise, n's pre was pointing to first before, and now that n has become first, pre points to null  
    --count;  
     notFull.signal();  // Notification of non-full condition queue  
    return item;  
}  
  
/** 
 *  remove end node, Returning an empty link tablenull 
 */  
private E unlinkLast() {  
    // assert lock.isHeldByCurrentThread();  
    Node<E> l = last;  
    if (l == null)  
        return null;  
    Node<E> p = l.prev;  
    E item = l.item;  
    l.item = null;  
    l.prev = l; // help GC  
    last = p;  
    if (p == null)  
        first = null;  
    else  
        p.next = null;  
    --count;  
    notFull.signal();  
    return item;  
}  
  
/** 
 *  remove Designated Nodes:p--》x--》n 
 */  
void unlink(Node<E> x) {  
    // assert lock.isHeldByCurrentThread();  
    Node<E> p = x.prev;  
    Node<E> n = x.next;   
     if (p == null) { //prev is null indicating that node x is the head node  
        unlinkFirst();  
    } else if (n == null) {  
         unlinkLast();  //nex is null means the node to be cleared is a tail node  
     } else { // otherwise the node is in the middle of the chain  
         p.next = n;  //Interlinking p and n  
        n.prev = p;  
        x.item = null;  
         // No x-node link is broken, there may be other threads iterating over the chain  
        --count;  
        notFull.signal();  
    }  
} 

2.7. peek method

    public E peek() {
        return peekFirst();
    }
    
    public E peekFirst() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return (first == null) ? null : first.item;
        } finally {
            lock.unlock();
        }
    }
    //peekLast I won't post it.

2.8. size method

    public int size() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return count;
        } finally {
            lock.unlock();
        }
    }

Third, the JDK or open source framework used in

IV. Examples of use

java.util.ArrayDeque class provides resizable of array, and achievedDeque interface。 The following is about the array double-ended queue of main point:Java.util.ArrayDeque

  • The array double-ended queue has no capacity limit, making them grow as necessary to support use.
  • They're not thread-safe; If there is no external sync.
  • Multi-threaded concurrent access is not supported.
  • The null element is forbidden to be used in the array deques.
  • They are faster than StackStack and LinkedList.

This class and its iterator implementation Collection and Iteratorinterfaces methods are optional.

Class Declaration

The following is the declaration for the java.util.ArrayDeque class.

public class ArrayDeque<E>
   extends AbstractCollection<E>
      implements Deque<E>, Cloneable, Serializable

here<E> Represents an element, It can be any class。 for example, If you are constructing a list of integer arrays, Then the initialization can be

ArrayList<Integer> list = new ArrayList<Integer>();

S.N.

approach & description

1

boolean add(E e) This method will add the specified of elemental, herebydeque formation of extremity。

2

void addFirst(E e) This method will add the specified of elemental, herebydeque formation of ahead。

3

void addLast(E e) This method will insertion designate of elemental, herebydeque formation of extremity。

4

void clear() this method remove thisdeque formation of elemental。

5

ArrayDeque<E> clone() This method returns thisdeque formation of copies。

6

boolean contains(Object o) If thisdeque The queue contains the specified of elemental, This method returnstrue。

7

Iterator<E> descendingIterator() This method returns an iterator in thisdeque The queue is in reverse order of elemental。

8

E element() This method retrieves, But no. remove thisdeque Queue representation of formation of head。

9

E getFirst() This method retrieves, But no. remove thisdeque formation of The first element。

10

E getLast() This method retrieves, But no. remove thisdeque formation of The last element。

11

boolean isEmpty() If thisdeque The queue does not contain elements, This method returnstrue。

12

Iterator<E> iterator() This method returns an iterator in thisdeque formation of elemental。

13

boolean offer(E e) This method takes the specified element, at the end of this deque queue.

14

boolean offerFirst(E e) This method will specify the of elemental, herebydeque formation of ahead。

15

boolean offerLast(E e) This method will specify the of elemental, herebydeque formation of extremity。

16

E peek() This method retrieves, But no. remove thisdeque Queue representation of formation of head, If thisdeque The queue is empty, returnsnull。

17

E peekFirst() This method retrieves, But no. remove thisdeque formation of The first element, Or if sodeque The queue is empty, returnsnull。

18

E peekLast() This method retrieves, But no. remove thisdeque formation of The last element, If thisdeque The queue is empty, returnsnull。

19

E poll() This method retrieves and remove thisdeque Queue representation of formation of head, If thisdeque The queue is empty, returnsnull。

20

E pollFirst() This method retrieves and remove thisdeque formation of The first element, Or if sodeque The queue is empty, returnsnull。

21

E pollLast() This method retrieves and remove thisdeque formation of The last element, If thisdeque The queue is empty, returnsnull。

22

E pop() This approach of thisdeque The queue represents of An element pops up in the stack。

23

void push(E e) This approach pushes elements heredeque The queue represents of stack。

24

E remove() This method retrieves and remove thisdeque Queue representation of formation of head。

25

boolean remove(Object o) This method has sincedeque In the queue remove The specified element of A single instance。

26

E removeFirst() This method retrieves and remove thisdeque formation of The first element。

27

boolean removeFirstOccurrence(Object o) this method remove thisdeque formation of The specified element of First match。

28

E removeLast() This method retrieves and remove thisdeque formation of The last element。

29

boolean removeLastOccurrence(Object o) this method remove thisdeque formation of The specified element of Last appearance。

30

int size() This method is returned heredeque formation of The number of elements。

31

object[] toArray() This method returns a containing all heredeque The queue is appropriate of The elements in the sequence of array。


Recommended>>
1、Removing a server in a SharePoint 2013 farm prompts a cacheHostInfoisnull error
2、Problems and solutions encountered when compiling RTKPlotQt version for Windows environment
3、PAT Level A 1020TreeTraversals binary tree traversal
4、A question mark in C syntax and two question marks What does the operator mean
5、Git Common Commands

    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    Contact US

    Welcome to Intefrankly.

    Intefrankly is a platform that you can show your opnions related to IT technology, and communicates to the people who interested in IT and Artificial Intelligence area.