Java BlockingQueue source code analysis, javablockingqueue

Source: Internet
Author: User

Java BlockingQueue source code analysis, javablockingqueue
Introduction

BlockingQueue is a multi-thread security blocking queue provided by Java concurrent. Its sub-classes include javasblockingqueue and ArrayBlockingQueue.

Key APIs

When it comes to queues, the insertion and deletion operations at the beginning and end are inevitable. BlockingQueue APIs provide several insertion and deletion methods.
When these methods encounter execution conditions that cannot be met, such as the queue is full (when an element is added)/the queue is empty (when an element is retrieved), different measures will be taken: throwing an exception, the return value is false/null, which blocks the thread that calls the API and waits for a certain period of time. The specific table is as follows:

Throws exception Special value Blocks Times out
Insert Add (e) Offer (e) Put (e) Offer (e, time, unit)
Remove Remove () Poll () Take () Poll (time, unit)
Examine Element () Peek () Not applicable Not applicable
ArrayBlockingQueue

ArrayBlockingQueue is an array-based blocking queue. When creating an ArrayBlockingQueue, you must provide a parameter indicating the queue size.

ArrayBlockingQueue is thread-safe, but how can this be done? Note the following three attributes:

    /** Main lock guarding all access */    final ReentrantLock lock;    /** Condition for waiting takes */    private final Condition notEmpty;    /** Condition for waiting puts */    private final Condition notFull;

Here is a lock and two condition variables that manage the mutex and synchronization of all the threads that use APIs. For more information about the locking and conditional variables, see related operating system books.

Offer vs put
    public boolean offer(E e) {        checkNotNull(e);        final ReentrantLock lock = this.lock;        lock.lock();        try {            if (count == items.length)                return false;            else {                insert(e);                return true;            }        } finally {            lock.unlock();        }    }    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();        }    }

We can see that when adding elements to the queue in the two methods, the key section is locked first. The difference is that if the queue is detected to be full in the offer method, false is directly returned. In the put method, if the queue is detected to be full, the thread will be blocked in the notFull condition variable, so that the thread will release the lock and let other threads enter the critical section. At a later time, a thread extracts elements from the queue. The queue is no longer empty, and the thread wakes up the thread that is blocked on the notFull condition variable. The put method can be completed.

Poll vs take
 public E take() throws InterruptedException {        final ReentrantLock lock = this.lock;        lock.lockInterruptibly();        try {            while (count == 0)                notEmpty.await();            return extract();        } finally {            lock.unlock();        }    }

The take logic is similar to put, except that if the queue is empty this time, the thread is blocked on the notEmpty condition variable and waits for other threads to add elements to the queue, and wake up the thread blocking on notEmpty.

   public E poll() {        final ReentrantLock lock = this.lock;        lock.lock();        try {            return (count == 0) ? null : extract();        } finally {            lock.unlock();        }    }

When the poll method detects that the queue is empty, null is directly returned. Otherwise, the Header element of the queue is taken out.

      public E poll(long timeout, TimeUnit unit) throws InterruptedException {        long nanos = unit.toNanos(timeout);        final ReentrantLock lock = this.lock;        lock.lockInterruptibly();        try {            while (count == 0) {                if (nanos <= 0)                    return null;                nanos = notEmpty.awaitNanos(nanos);            }            return extract();        } finally {            lock.unlock();        }    }

Poll also has an interesting overload implementation. Here we use the timer method of the Condition variable awaitNanos. First, convert the time size to the value of the nanosecond according to the time unit. When the queue capacity is 0, use Condition. awaitNanos (...), Timed out, return null after timeout.

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.