Concurrent开头的容器往往就是线程安全的队列,支持并发。
不过Concurrent类型的容器没有CopyOnWrite之类的容器那样相对较重的修改开销,不过具有较低的遍历一致性,例如在遍历时容易发生“fast-fail”行为,抛出ConcurrentModificationException异常。
线程安全队列有如下几种:

关于BlockingQueue是否有界问题:
- LinkedBlockingQueue如果在未指定容量时,那么默认会设置成Integer.MAX_VALUE大小,也就是无界队列。
在newFixedThreadPool和newSingleThreadExecutor线程池中采用的就是LinkedBlockingQueue阻塞任务队列,所有它们允许的请求队列长度为Integer.MAX_VALUE。
- SynchronousQueue:每个删除操作都要等待插入操作,每个插入操作也要等待删除操作,其内部容量就0。
在newCachedThreadPool线程池中作为阻塞任务队列使用。
- PriorityBlockingQueue是无边界的优先队列。
- DelayedQueue和LinkedTransferQueue同样是无边界队列。
以LinkedBlockingQueue、 ArrayBlockingQueue和SynchronousQueue为例,我们一起来分析一下,根据需求可以从很多方面考量:c
- 考虑应用场景中对队列边界的要求。 ArrayBlockingQueue是有明确的容量限制的,而LinkedBlockingQueue则取决于我们是否在创建时指定, SynchronousQueue则干脆不能缓存任何元素。
- 从空间利用角度,数组结构的ArrayBlockingQueue要比LinkedBlockingQueue紧凑,因为其不需要创建所谓节点,但是其初始分配阶段就需要一段连续的空间,所以初始内存需求更大。
- 通用场景中, LinkedBlockingQueue的吞吐量一般优于ArrayBlockingQueue,因为它实现了更加细粒度的锁操作。
- ArrayBlockingQueue实现比较简单,性能更好预测,属于表现稳定的“选手”。
- 如果我们需要实现的是两个线程之间接力性(handof)的场景,按照专栏上一讲的例子,你可能会选择CountDownLatch,但是SynchronousQueue也是完美符合这种场景的,而且线程间协调和数据传输统一起来,代码更加规范。
- 可能令人意外的是,很多时候SynchronousQueue的性能表现,往往大大超过其他实现,尤其是在队列元素较小的场景。
网友评论