PriorityBlockingQueue 听上去是“按优先级的 BlockingQueue”,实际有四个常被忽略的边界:同优先级无序、遍历顺序不是优先级顺序、元素字段不能变、没有容量上限。这篇逐项量出来,并给出让它可用的做法。
12 个优先级都是 1 的任务按 t0..t11 入队,出队顺序:[t0, t11, t10, t9, t8, t7, t6, t5, t4, t3, t2, t1](是否与入队顺序相同:false) 加上序号作第二比较键(thenComparingLong(seq)):[t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11] 依次放入 9 3 7 1 8 2 6:toString() = [1, 3, 2, 9, 8, 7, 6];poll 顺序 = [1, 2, 3, 6, 7, 8, 9];stream 的顺序 = [1, 3, 2, 9, 8, 7, 6] 没有比较器时 put(new Object()):ClassCastException:class java.lang.Object cannot be cast to class java.lang.Comparable (java.lang.Object and …
j0..j5 优先级 10..15;把 j5 的优先级改成 1 之后(没有重新入队):peek() = j0:10,poll 顺序 = [j0:10, j5:1, j1:11, j2:12, j3:13, j4:14] 先 remove 再改再 put:poll 顺序 = [j5:1, j0:10, j1:11, j2:12, j3:13, j4:14]
纯按 prio 排序:3 秒内处理了 6003 个任务;低优先级任务3 秒内一直没有被取到,队列里积压 471 按“创建时间 + prio × 20 ms”排序(越旧越优先):3 秒内处理了 6017 个任务;低优先级任务在 2224 ms 时被取到
无界队列 put 持续放入 1 KiB 数组,-Xmx64m 下放入 62809 个(约 61 MiB)后 OutOfMemoryError:Java heap space 用 Semaphore(1000) 限界:2 秒内生产 2322,消费 1322,队列里 1000(不会超过 1000),无 OOM