Arrayblockingqueue Source Analysis

Source: Internet
Author: User
Producer-Consumer

Arrayblockingqueue is a class that implements the Blockingqueue interface, and it can easily realize the producer-consumer model. Usage is as follows:

 Class Producer implements Runnable {
    private final blockingqueue queue;
    Producer (Blockingqueue q) {queue = q;}
    public void Run () {
      try {while
        (true) {queue.put (produce ());}
      catch (Interruptedexception ex) {... Handl E..}}
    Object Produce () {...}}
  }

  Class Consumer implements Runnable {
    private final blockingqueue queue;
    Consumer (Blockingqueue q) {queue = q;}
    public void Run () {
      try {while
        (true) {consume (Queue.take ());}
      catch (Interruptedexception ex) {... h Andle ...}
    }
    void consume (Object x) {...}
  }

  Class Setup {
    void main () {
      Blockingqueue q = new somequeueimplementation ();
      Producer p = new Producer (q);
      Consumer C1 = new Consumer (q);
      Consumer C2 = new Consumer (q);
      New Thread (P). Start ();
      New Thread (C1). Start ();
      New Thread (C2). Start ();
    }
  }
two-condition algorithm for concurrency control

The following three variable declarations (definitions) are available in Arrayblockingqueue:


 * * Concurrency control uses the classic two-condition algorithm-found in any
 textbook.
 * *

/** Main lock Guarding All Access
/final reentrantlock lock;
/** Condition for Waiting takes * *
private final Condition notempty;
/** Condition for waiting puts * *
private final Condition notfull;

The realization of producer-consumer concurrency control is simple, a lock, two conditions. Let's look at the Arrayblockingqueue constructor code:

public arrayblockingqueue (int capacity, Boolean fair) {
    if (capacity <= 0)
        throw new IllegalArgumentException ();
    This.items = new Object[capacity];
    lock = new Reentrantlock (fair);
    Notempty = Lock.newcondition ();
    Notfull =  lock.newcondition ();
}

During initialization, Arrayblockingqueue initializes the lock, Notempty, and Notfull. production by producers

First look at the put (e E) method that needs to be invoked at producer production Time:

public void put (e e) throws interruptedexception {
    checknotnull (e);
    Final Reentrantlock lock = This.lock;
    Lock.lockinterruptibly ();
    try {while
        (count = = items.length)
            notfull.await ();
        Insert (e);
    } finally {
        lock.unlock ();
    }
}

First, the Reentrantlock lockinterruptibly () method is used to try to acquire the lock, which, after acquiring the lock, can continue to respond to the interrupt operation of the thread, noting that Lock.unlock () must be written in the finally block. Otherwise, the lock may never be released after an exception is found.

When the current number is found to be full: while (count = = Items.length), the producer (the current thread) is expected to wait: notfull.await (), otherwise the Insert (e) operation is performed.

Continue tracking Insert (e) Operation it is not difficult to think that after the insert succeeds, the Notempty will be notified to wake the consumer (a thread that is waiting for the notempty condition) to inform the new product to be consumed.

private void Insert (E x) {
    Items[putindex] = x;
    Putindex = Inc (PUTINDEX);
    ++count;
    Notempty.signal ();
}

As you know: If the queue is full, then notfull to wait, or after the insertion of success, wake up Notempty told not to wait. Similarly: The take of consumer consumption is similar. consumers to consume

Public E take () throws Interruptedexception {
    final reentrantlock lock = This.lock;
    Lock.lockinterruptibly ();
    try {while
        (count = = 0)
            notempty.await ();
        return extract ();
    } finally {
        lock.unlock ();
    }
}

Private E Extract () {
    final object[] items = this.items;
    E x = This.<e>cast (Items[takeindex]);
    Items[takeindex] = null;
    Takeindex = Inc (TAKEINDEX);
    --count;
    Notfull.signal ();
    return x;
}
Summarize

On the whole, after Reentrantlock and condition, the producer-consumer model is easy to implement. Reentrantlock is responsible for locking the release lock, condition is responsible for waiting for the wake thread.

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.