concurrentlinkedqueue的iterator()返回弱一致性迭代器,不抛出concurrentmodificationexception,允许并发修改,但不保证遍历所有元素或反映实时状态,仅尽力遍历已到达且未被移除的节点。

ConcurrentLinkedQueue 的 iterator() 方法提供的是弱一致性(weakly consistent)迭代器,不是实时快照,也不保证反映某一时刻的完整队列状态。
弱一致性迭代器的核心特点
它不抛出 ConcurrentModificationException,允许在迭代过程中有其他线程并发修改队列;但不保证看到所有已存在的元素,也可能重复返回某些元素,或遗漏正在被修改的元素。
- 迭代器基于当前节点链表结构“尽力而为”地遍历,不会加锁也不会阻塞写操作
- 它只保证遍历时已到达且未被移除的节点会被访问一次(但不保证“所有”节点都被访问)
- 新增的节点如果在迭代器当前位置之后插入,可能被看到;如果插在前面或中间,大概率被跳过
- 删除操作若发生在迭代器尚未到达的节点上,该节点将不会出现在迭代结果中
为什么设计成弱一致性?
这是为了在高并发场景下兼顾性能与可用性。强一致性(如加锁或复制快照)会显著降低吞吐量,而 ConcurrentLinkedQueue 的目标是无锁、高吞吐的非阻塞队列。
- 避免因迭代导致写操作长时间等待
- 不依赖全局状态同步,符合 lock-free 设计哲学
- 适用于“近似统计”“日志采样”等对精确性要求不高的场景
使用时需要注意什么?
不能依赖迭代结果做精确判断(比如检查是否包含某元素、计算准确 size),也不能用于需要严格顺序或完整性的逻辑。
- 不要用
for-each循环做条件判断或状态同步,例如if (queue.contains(x)) {...}应改用queue.contains(x)直接调用(它本身也是弱一致的,但语义更明确) - 避免在迭代中调用
remove()—— 迭代器的remove()方法在 ConcurrentLinkedQueue 中是 不支持的,会抛出UnsupportedOperationException - 若需强一致性视图,应自行加锁或使用其他结构(如
CopyOnWriteArrayList,但注意适用场景和开销)
实际例子说明行为差异
假设队列初始为 [A, B, C],线程 T1 开始迭代,刚访问完 A;此时线程 T2 执行 offer(D) 并成功插入到 C 后;T1 迭代器后续可能看到 D,也可能看不到——取决于 CAS 操作完成时迭代器指针的位置。
- 若 T2 在 T1 读取 next 指针前完成插入,T1 可能遍历到 D
- 若 T2 插入后 T1 已经读取了 C 的 next 为 null,则 D 不会被访问
- 若 T2 同时移除了 B,而 T1 还未到达 B,那 B 就彻底“消失”在本次迭代中
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











