Java线程(14):阻塞队列BlockingQueue
言归正传,这一段时间我的工作主要是改进公司的调度器,调度器调度线程池执行任务,生产者生产任务,消费者消费任务,那么这时就需要一个任务队列,生产者向队列里插入任务,消费者从队列里提取任务执行,调度器里是通过BlockingQueue
实现的队列,随后小查一下,下面看看BlockingQueue
的原理及其方法。
ArrayBlockingQueue
LinkedBlockingDeque
DelayQueue
PriorityBlockingQueue
-
SynchronousQueue
BlockingQueue
最终会有四种状况,抛出异常、返回特殊值、阻塞、超时,下表总结了这些方法:
- | 抛出异常 | 特殊值 | 阻塞 | 超时 |
---|---|---|---|---|
插入 | add(e) |
offer(e) |
put(e) |
offer(e, time, unit) |
移除 | remove() |
poll() |
take() |
poll(time, unit) |
检查 | element() |
peek() |
不可用 | 不可用 |
BlockingQueue
是个接口,有如下实现类:
ArrayBlockQueue
:一个由数组支持的有界阻塞队列。此队列按FIFO
(先进先出)原则对元素进行排序。创建其对象必须明确大小,像数组一样。LinkedBlockQueue
:一个可改变大小的阻塞队列。此队列按FIFO
(先进先出)原则对元素进行排序。创建其对象如果没有明确大小,默认值是Integer.MAX_VALUE
。链接队列的吞吐量通常要高于基于数组的队列,但是在大多数并发应用程序中,其可预知的性能要低。PriorityBlockingQueue
:类似于LinkedBlockingQueue
,但其所含对象的排序不是FIFO
,而是依据对象的自然排序顺序或者是构造函数所带的Comparator
决定的顺序。SynchronousQueue
:同步队列。同步队列没有任何容量,每个插入必须等待另一个线程移除,反之亦然。
下面使用ArrayBlockQueue
来实现之前实现过的生产者消/费者模式,代码如下:
1
|
/** 定义一个盘子类,可以放鸡蛋和取鸡蛋 */
|
执行结果:
1
|
放入鸡蛋
|
从结果看,启动10
个放鸡蛋线程和10
个取鸡蛋线程,前5
个放入鸡蛋的线程成功执行,到第6
个,发现盘子满了,阻塞住,这时切换到取鸡蛋线程执行,成功实现了生产者/消费者模式。java.util.concurrent
包是个强大的包!