java 链表并发队列 LinkedBlockingQueue 的坑
程序员文章站
2022-06-17 10:06:59
...
链个队比数组队的性能要高, 所以一般用 LinkedBlockingQueue 比较多, 之前并没有注意各方法有什么不同.
环境: JDK 1.8
今天发现在 LinkedBlockingQueue 有个坑:
入队方法 add不能随意使用 :
LinkedBlockingQueue< String > receiveQueue = new LinkedBlockingQueue< String >();
receiveQueue.add("123");
会导致在出队线程处理中 poll() 无法及时取得值:
/**
* 独立处理 队列线程
*/
private class receiveThread implements Runnable{
@Override
public void run() {
String msg = null;
while (receNext) {
try {
msg = receiveQueue.poll();
if(msg != null) {
//处理消息....
logger.info("接收数据:"+ msg );
} else {
Thread.sleep(2000);
}
}catch (Exception e) {
logger.error("接收线程异常", e);
} finally {
}
}
}
}
经过查看原代码, add方法在此类中没有重写, 入队之后, 并没有触发操作, 因此是个坑.
重现的代码环境是:
1, add方法与poll所在的线程是在同一个类中, add在类方法中调用, poll 内部类线程中调用.
2, poll的线程一直在运行, 当程序中其它代码(程序另一个线程中) 调用 add在一个方法后, poll并没有取得值.
经测试, 这时如果要poll要取得值必须 在poll之前调用 size() 才能让poll取得值. 否则 poll在测试的 10多秒后仍然得到空值.
3, 以上是在多线程环境时出现的, 如果在同一段代码中先 add再 poll这样测试, 是可以正常取得值的.
经过测试与查看源代码, 在此类中 出队方法 receiveQueue.take(), 入队方法 receiveQueue.put(E o) 应配合使用.
由于时间限制其它方法没有再详细测试.
推荐阅读
-
详细分析Java并发集合LinkedBlockingQueue的用法
-
Java并发 之 阻塞队列LinkedBlockingQueue与ArrayBlockingQueue
-
java 链表并发队列 LinkedBlockingQueue 的坑
-
JAVA并发(5)-并发队列LinkedBlockingQueue的分析
-
Java并发47:并发集合系列-基于CAS算法的非阻塞单向*队列ConcurrentLinkedQueue
-
Java并发 之 阻塞队列LinkedBlockingQueue与ArrayBlockingQueue
-
java高并发编程:4--Java中的阻塞队列
-
java 基于链表的队列 队列
-
java中关于队列的数组和链表实现
-
并发编程(九)—— Java 并发队列 BlockingQueue 实现之 LinkedBlockingQueue 源码分析