LinkedTransferQueue 比普通无界队列多了“生产者可以等消费者”。这篇量出它的方法语义、transfer 到底在等什么、做背压的效果,以及无界队列容易被忽略的 size() 成本和吞吐的不确定性。
tryTransfer("a"):false;之后 size() = 0(没有消费者,元素没有入队)
tryTransfer("b", 200 ms):false,耗时约 208 ms;之后 size() = 0(超时后元素被移除)
put("c") 立即返回;size() = 1,hasWaitingConsumer() = false
poll() = c
transfer("d") 阻塞 300 ms 期间:size() = 1,peek() = d,线程状态 WAITING
take() = d
生产者 transfer("d") 在 323 ms 后返回
一个消费者在 take() 等待时:hasWaitingConsumer() = true,getWaitingConsumerCount() = 1;tryTransfer("e") = true队列里 [1, 2, 3],另一个线程 transfer(99) 已等待 100 ms:size() = 4(99 在队尾,[1, 2, 3, 99]) 1 个元素被取走后(+100 ms):取到 1,transfer 线程状态 WAITING 2 个元素被取走后(+200 ms):取到 2,transfer 线程状态 WAITING 3 个元素被取走后(+300 ms):取到 3,transfer 线程状态 WAITING 取走 99 之前 transfer 线程状态 WAITING;取走 99:99 transfer(99) 总共等了约 555 ms(= 排在前面的 3 个元素被取走 + 99 本身被取走)
LinkedTransferQueue.put 1 秒内生产 14335204,消费 183,队列里积压 17978953 LinkedTransferQueue.transfer 1 秒内生产 537,消费 537,队列里积压 1 ArrayBlockingQueue(100).put 1 秒内生产 772,消费 672,队列里积压 100
1000 个元素:LinkedTransferQueue.size() 最快一次约 15 µs,LinkedBlockingQueue.size() 约 84 ns 100000 个元素:LinkedTransferQueue.size() 最快一次约 191 µs,LinkedBlockingQueue.size() 约 42 ns 1000000 个元素:LinkedTransferQueue.size() 最快一次约 1316 µs,LinkedBlockingQueue.size() 约 0 ns LinkedTransferQueue.remainingCapacity() = 2147483647(没有容量上限)
1 对 LinkedTransferQueue 每个对象约 43 ns(中位数,共 170 ms) 1 对 LinkedBlockingQueue 每个对象约 138 ns(中位数,共 551 ms) 1 对 ConcurrentLinkedQueue(自旋) 每个对象约 38 ns(中位数,共 152 ms) 4 对 LinkedTransferQueue 每个对象约 179 ns(中位数,共 714 ms) 4 对 LinkedBlockingQueue 每个对象约 73 ns(中位数,共 292 ms) 4 对 ConcurrentLinkedQueue(自旋) 每个对象约 163 ns(中位数,共 650 ms)