Java BlockingQueue阻塞队列
Posted hequnwang10
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java BlockingQueue阻塞队列相关的知识,希望对你有一定的参考价值。
一、定义
BlockingQueue其实就是阻塞队列,是基于阻塞机制实现的线程安全的队列。而阻塞机制的实现是通过在入队和出队时加锁的方式避免并发操作。
BlockingQueue不同于普通的Queue的区别主要是:
- 通过在入队和出队时进行加锁,保证了队列线程安全
- 支持阻塞的入队和出队方法:当队列满时,会阻塞入队的线程,直到队列不满;当队列为空时,会阻塞出队的线程,直到队列中有元素。
BlockingQueue常用于生产者-消费者模型中,往队列里添加元素的是生产者,从队列中获取元素的是消费者;通常情况下生产者和消费者都是由多个线程组成。
二、BlockingQueue 的方法
public interface BlockingQueue<E> extends Queue<E>
/**
* 入队一个元素,如果有空间则直接插入,并返回true;
* 如果没有空间则抛出IllegalStateException
*/
boolean add(E e);
/**
* 入队一个元素,如果有空间则直接插入,并返回true;
* 如果没有空间返回false
*/
boolean offer(E e);
/**
* 入队一个元素,如果有空间则直接插入,如果没有空间则一直阻塞等待
*/
void put(E e) throws InterruptedException;
/**
* 入队一个元素,如果有空间则直接插入,并返回true;
* 如果没有空间则等待timeout时间,插入失败则返回false
*/
boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException;
/**
* 出队一个元素,如果存在则直接出队,如果没有空间则一直阻塞等待
*/
E take() throws InterruptedException;
/**
* 出队一个元素,如果存在则直接出队,如果没有空间则等待timeout时间,无元素则返回null
*/
E poll(long timeout, TimeUnit unit) throws InterruptedException;
/**
* 返回该队列剩余的容量(如果没有限制则返回Integer.MAX_VALUE)
*/
int remainingCapacity();
/**
* 如果元素o在队列中存在,则从队列中删除
*/
boolean remove(Object o);
/**
* 判断队列中是否存在元素o
*/
public boolean contains(Object o);
/**
* 将队列中的所有元素出队,并添加到给定的集合c中,返回出队的元素数量
*/
int drainTo(Collection<? super E> c);
/**
* 将队列中的元素出队,限制数量maxElements个,并添加到给定的集合c中,返回出队的元素数量
*/
int drainTo(Collection<? super E> c, int maxElements);
BlockingQueue 具有 4 组不同的方法用于插入、移除以及对队列中的元素进行检查。如果请求的操作不能得到立即执行的话,每个方法的表现也不同。这些方法如下:
- 抛异常: 如果试图的操作无法立即执行,抛一个异常。
- 特定值: 如果试图的操作无法立即执行,返回一个特定的值(常常是 true / false)。
- 阻塞: 如果试图的操作无法立即执行,该方法调用将会发生阻塞,直到能够执行。
- 超时: 如果试图的操作无法立即执行,该方法调用将会发生阻塞,直到能够执行,但等待时间不会超过给定值。返回一个特定值以告知该操作是否成功(典型的是 true / false)。
无法向一个 BlockingQueue 中插入 null。如果你试图插入 null,BlockingQueue 将会抛出一个 NullPointerException。
可以访问到 BlockingQueue 中的所有元素,而不仅仅是开始和结束的元素。比如说,你将一个对象放入队列之中以等待处理,但你的应用想要将其取消掉。那么你可以调用诸如 remove(o) 方法来将队列之中的特定对象进行移除。但是这么干效率并不高(译者注: 基于队列的数据结构,获取除开始或结束位置的其他对象的效率不会太高),因此你尽量不要用这一类的方法,除非你确实不得不那么做。
三、BlockingQueue实现类及原理
主要实现类
其中在日常开发中用的比较多的是ArrayBlockingQueue和LinkedBlockingQueue,本文也将主要介绍这两个实现类的原理。
1、ArrayBlockingQueue的用法和原理
ArrayBlockingQueue是基于数组实现的阻塞队列。
是一个有界的阻塞队列,其内部实现是将对象放到一个数组里。有界也就意味着,它不能够存储无限多数量的元素。它有一个同一时间能够存储元素数量的上限。你可以在对其初始化的时候设定这个上限,但之后就无法对这个上限进行修改了(译者注: 因为它是基于数组实现的,也就具有数组的特性: 一旦初始化,大小就无法修改)。
ArrayBlockingQueue 内部以 FIFO(先进先出)的顺序对元素进行存储。队列中的头元素在所有元素之中是放入时间最久的那个,而尾元素则是最短的那个。
以上是关于Java BlockingQueue阻塞队列的主要内容,如果未能解决你的问题,请参考以下文章
Java数据结构及算法实战系列008:Java队列02——阻塞队列BlockingQueue
Java数据结构及算法实战系列008:Java队列02——阻塞队列BlockingQueue
Java阻塞队列BlockingQueue(生产者消费者模型)