java 线程池工作队列
线程池工作队列
上一章我们介绍了线程的基本情况,这一章进一步了解线程池中的工作队列,BlockingQueue 队列。
在类 Executors 中,我们可以看到不同线程池维护的工作队列是不同的,如newCachedThreadPool使用的是SynchronousQueue 同步队列,newSingleThreadScheduledExecutor使用DelayedWorkQueue, newFixedThreadPool和newScheduledThreadPool使用LinkedBlockingQueue。它们都是实现了并发包java.util.concurrent中的BlockingQueue,下面说说这个接口。
BlockingQueue 阻塞队列
继承于队列 Queue,遵循先进先出原则(FIFO),队列提供几种基本的操作,添加元素(队尾)、移除元素(队头)、取出队头元素(不移除),每种操作都有两个方法,一种有可能抛异常,一种返回操作成功或失败。
在这个基础上,阻塞队列增加了操作锁,保证了数据安全,当然这个具体实现是在子类中完成,接口仅仅描述方法的特点,还增加两种不同的操作实现。下面描述这四种不同类型的操作:
- 操作,可能抛异常
- 操作,不抛异常(特殊如类转换异常、空指针、参数异常不属于,仅当队列已满不会跑状态异常)
- 无限期阻塞线程直至操作成功
- 有时间限制的操作
| 添加 | 移除 | 检查 |
|---|---|---|
| add(e) | remove(o) | element() |
| offer(e) | poll() | peek() |
| put(e) | take() | \ |
| offer(e,time,unit) | poll(time,unit) | \ |
以及增加了拷贝 drainTo,如线程池的 shutdownNow就是用它完成工作队列的清除以及队列中数据的拷贝,还有其他如对比元素contains,剩余容量查询remainingCapacity等。
实现的子类
- ArrayBlockingQueue 数组型阻塞队列
- LinkedBlockingQueue 链表型阻塞队列
- DelayQueue 延时队列
- SynchronousQueue 同步队列
- PriorityBlockingQueue 优先阻塞队列
ArrayBlockingQueue
特点:
- 初始化一定容量的数组
- 使用一个重入锁,默认使用非公平锁,入队和出队共用一个锁,互斥
- 是有界设计,如果容量满无法继续添加元素直至有元素被移除
- 使用时开辟一段连续的内存,如果初始化容量过大容易造成资源浪费,过小易添加失败
LinkedBlockingQueue
特点:
- 内部使用节点关联,会产生多一点内存占用
- 使用两个重入锁分别控制元素的入队和出队,用
Condition进行线程间的唤醒和等待 - 有边界的,在默认构造方法中容量是
Integer.MAX_VALUE - 非连续性内存空间
- 使用两个重入锁分别控制元素的入队和出队,用
DelayQueue
特点:
- 无边界设计
- 添加(put)不阻塞,移除阻塞
- 元素都有一个过期时间
- 取元素只有过期的才会被取出
SynchronousQueue
特点:
- 内部容量是0
- 每次删除操作都要等待插入操作
- 每次插入操作都要等待删除操作
- 一个元素,一旦有了插入线程和移除线程,那么很快由插入线程移交给移除线程,这个容器相当于通道,本身不存储元素
- 在多任务队列,是最快的处理任务方式。
PriorityBlockingQueue
特点:
- 无边界设计,但容量实际是依靠系统资源影响
- 添加元素,如果超过1,则进入优先级排序

浙公网安备 33010602011771号