You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java内置ArrayBlockingQueue与自定义队列实现中双入队线程的异常行为问题

Java内置ArrayBlockingQueue与自定义队列实现中双入队线程的异常行为问题

嗨,我来帮你拆解下这个问题的根源~

核心误解与问题原因

你遇到的“乱序”问题,本质是对线程并发执行逻辑和ArrayBlockingQueue的工作特性存在两点认知偏差:

  • 线程add操作并非串行执行:你启动的t1和t2是并发运行的,操作系统会在两个线程之间动态切换CPU时间片,它们的add操作不会严格按“t1加完20个再t2加”的顺序执行。比如t1刚完成i=9的add(加入元素9),系统可能切换到t2执行i=0的add(加入元素0),再切回t1执行i=10的add(加入元素10),这样队列内的元素顺序就会变成0,1,...,9,0,10,11,...,这直接导致后续poll时出现“跨线程的乱序元素”。
  • poll操作是共享队头的竞争行为:两个线程共用同一个ArrayBlockingQueue,poll方法始终从队列头部取出元素,不管这个元素是哪个线程加入的。也就是说,t1的poll可能取到t2加入的元素,t2的poll也可能取到t1加入的元素;再加上poll阶段也是并发执行的,两个线程会竞争取队头元素,最终输出顺序自然是混合且不符合你预期的“线程内顺序”。

结合你的代码与输出分析

比如你输出里的第一个0,其实是t2加入的(0*2000=0),而t1自己加入的0可能早被其中一个线程poll走了;后面15出现在2000、4000之后,是因为t1在加入15之前,t2已经完成了i=1和i=2的add(加入2000、4000),这些元素排在队列里15的前面,随后被某个线程优先poll出来。

解决方案建议

如果想要实现“每个线程只处理自己加入的元素”,可以尝试两种思路:

  • 给每个线程分配独立的队列,彻底隔离不同线程的元素;
  • 在加入队列的元素中标记线程归属,poll时过滤出属于当前线程的元素(不过这种方式会增加逻辑复杂度,还可能导致队列阻塞风险)。

备注:内容来源于stack exchange,提问作者Adrian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 03:18:15