Blocking Queue in Java

One: the concept of blocking queue

        A blocking queue is a queue that supports two additional operations. These two additional operations support blocking insert and remove methods.

     Blocking insert: put method, when the queue is full, the queue will block the thread that inserts the element until the queue is full.

     Blocking removal: take method, when the queue is empty, the thread that gets the element will wait for the queue to become non-empty.

 

        The BlockingQueue method comes in four forms. For operations that cannot be satisfied immediately but may be satisfied at some point in the future, these four forms are handled differently: the first is to throw an exception, and the second is to return a special value (null or false, depending on the operation), the third is to block the current thread indefinitely until the operation can succeed, and the fourth is to block only for a given maximum time limit before giving up.

 

 

Throw an exception

special value

block

time out

insert

add(e)

offer(e)

put(e)

offer(e, time, unit)

remove

remove()

poll()

take()

poll(time, unit)

an examination

element()

peek()

unavailable

unavailable

Two: the characteristics of blocking queue

① Inserting null values ​​is not allowed

    BlockingQueue  does not accept null  elements.  Some implementations throw NullPointerException when trying to add , put ,  or offer  a null element . null  is used as a guard value to indicate that the poll  operation failed.

②Thread safety

        The BlockingQueue  implementation is thread safe. All queuing methods can use internal locks or other forms of concurrency control to achieve their purpose automatically

③Constant volume (with capacity)

        BlockingQueue  can be limited capacity. It can have a remainingCapacity at any given time , beyond which  additional elements cannot be put non-blocking. A BlockingQueue without any internal capacity constraints  always reports  the remaining capacity of Integer.MAX_VALUE .

Three: Implementation class of blocking queue

①ArrayBlockingQueue

        ArrayBlockingQueue is a bounded blocking queue implemented with arrays. The secondary queue sorts the elements on a first-in-first-out (FIFO) basis.

This class supports an optional fairness strategy for ordering waiting producer and consumer threads. By default, this ordering is not guaranteed. However, a queue constructed by setting fairness to true  allows threads to be accessed in FIFO order. Fairness generally reduces throughput, but also reduces variability and avoids "imbalance".

ArrayBlockingQueue (int capacity) creates an ArrayBlockingQueue           with the given (fixed) capacity and default access policy . 

ArrayBlockingQueue (int capacity, boolean fair) Creates an ArrayBlockingQueue           with the given (fixed) capacity and the specified access policy . 

Visitor fairness is achieved using reentrant locks.


②LinedBlockingQueue

LinedBlockingQueue是一个用链表实现的有界阻塞队列。此队列的默认最大长度为Integer.MAX_VALUE。此队列按照先进先出的原则对元素进行排序。


③PriorityBlockinQueue

PriorityBlockinQueue进行的操作不保证具有同等优先级的元素的顺序。如果需要实施某一排序,那么可以定义自定义类实现compareTo()方法或者比较器Comparator,比较器可使用修改键断开主优先级值之间的联系。

 

④DelayQueue

DelayQueue是一个支持延时获取元素的无界阻塞队列。队列使用PriorityQueue来实现。队列中的元素必须实现Delayed接口。创建元素时可以指定多久才可以从队列中获取当前元素。

DelayQueue可以应用的场景:缓存系统的设计、定时任务的调度。

实现Delayed接口:

 long

getDelay(TimeUnit unit) 
          返回与此对象相关的剩余延迟时间,以给定的时间单位表示。

 

第一步:创建对象的时候,初始化基本数据。使用time记录当前对象延迟到什么时候可以使用,使用sequenceNumber来标识元素在队列中的先后顺序。

第二步:实现getDelay方法

第三步:实现compareTo方法指定元素的顺序。


SynchronousQueue

        SynchronousQueue是一个存储元素的阻塞队列每一个put操作必须等待一个take操作。

 

⑥LinkedBlockingDeque

        LinkedBlockingDeque是一个由链表结构组成的双向阻塞队列。所谓双向队列指的是可以从队列的两端插入和移除元素。

 

 

四:阻塞队列的实现原理

    /** Condition for waiting takes */

    private final Condition notEmpty;

    /** Condition for waiting puts */

    private final Condition notFull;

我们查看源代码,可以看出ArrayBlockingQueue使用了Condition来实现通知模式的。

 public void put(E e) throws InterruptedException {

        checkNotNull(e);

        final ReentrantLock lock = this.lock;

        lock.lockInterruptibly();

        try {

            while (count == items.length)

                notFull.await();

            enqueue(e);

        } finally {

            lock.unlock();

        }

    }

 

    public E take() throws InterruptedException {

        final ReentrantLock lock = this.lock;

        lock.lockInterruptibly();

        try {

            while (count == 0)

                notEmpty.await();

            return dequeue();

        } finally {

            lock.unlock();

        }

    }

 


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325527463&siteId=291194637