并发包中的ConcurrentLinkedQueue和LinkedBlockingQueue有什么区别?
在上一讲中,我分析了Java并发包中的部分内容,今天我来介绍一下线程安全队列。Java标准库提供了非常多的线程安全队列,很容易混淆
今天我要问你的问题是,并发包中的ConcurrentLinkedQueue和LinkedBlockingQueue有什么区别?
典型回答
-
有时候我们把并发包下面的所有容器都习惯叫作并发容器,但是严格来讲,类似ConcurrentLinkedQueue这种“Concurrent*”容器,才是真正代表并发 -
关于问题中它们的区别:
- Concurrent类型基于lock-free,在常见的多线程访问场景,一般可以提供较高吞吐量
- 而LinkedBlockingQueue内部则是基于锁,并提供了BlockingQueue的等待性方法
-
不知道你有没有注意到,java.util.concurrent包提供的容器(Queue、List、Set)、Map,从命名上可以大概区分为Concurrent、CopyOnWrite和Blocking等三类,同样是线程安全容器,可以简单认为:
- Concurrent类型没有类似CopyOnWrite之类容器相对较重的修改开销
- 但是,凡事都是有代价的,Concurrent往往提供了较低的遍历一致性。你可以这样理解所谓的弱一致性,例如,当利用迭代器遍历时,如果容器发生修改,迭代器仍然可以继续 进行遍历
- 与弱一致性对应的,就是我介绍过的同步容器常见的行为“fast-fail”,也就是检测到容器在遍历过程中发生了修改,则抛出ConcurrentModifcationException,不再继续遍历
- 弱一致性的另外一个体现是,size等操作准确性是有限的,未必是100%准确
- 与此同时,读取的性能具有一定的不确定性。
考点分析
今天的问题是又是一个引子,考察你是否了解并发包内部不同容器实现的设计目的和实现区别
|