DelayQueue 是“到期才可取”的优先级队列,常被用来写本地缓存过期和定时任务。这篇量出它的语义细节、compareTo 写错时的队头阻塞、到期精度、多消费者行为和取消成本。
放入 a(200 ms)、b(400 ms)、c(600 ms);t=0:size() = 3,isEmpty() = false,peek() = a(堆顶是最早到期的),poll() = null iterator 遍历:[a, c, b](含未到期元素),remainingCapacity() = 2147483647 take() 返回 a,等了约 187 ms(预期 200) 再 take() 返回 b,累计约 394 ms(预期 400) 又睡 300 ms(此时 c 已到期):size() = 1,poll() = c,size() = 0
400 ms 后(B 已到期 300 ms):poll() = null,size() = 2,peek() = A,peek().getDelay = 1589 ms poll(3 s) 返回 A,等了约 1581 ms;之后 poll() 取到 B,此时 B 比它的到期时刻晚了约 1900 ms 对照:compareTo 按到期时间比较,400 ms 后 poll() = B
空闲:取到元素时比到期时间晚(微秒)p50 = 340,p99 = 7890,max = 7919 8 个空转线程:取到元素时比到期时间晚(微秒)p50 = 343,p99 = 4907,max = 4994
500 ms 后:取到元素的消费者 1 个,仍在等待的消费者 3 个
队列里 1000 个元素(取消最晚到期的 200 个,第 3 次重复):DelayQueue.remove 每次约 1111 ns;ScheduledThreadPoolExecutor(removeOnCancel)cancel 每次约 856 ns 队列里 10000 个元素(取消最晚到期的 200 个,第 3 次重复):DelayQueue.remove 每次约 3440 ns;ScheduledThreadPoolExecutor(removeOnCancel)cancel 每次约 743 ns 队列里 100000 个元素(取消最晚到期的 200 个,第 3 次重复):DelayQueue.remove 每次约 31788 ns;ScheduledThreadPoolExecutor(removeOnCancel)cancel 每次约 39 ns