最近学习了 BlockingQueue,发现 java 的 BlockingQueue 并不是每一个实现都按照 BlockingQueue 的语意来的,其中有不少坑。
直接上代码吧:
1、关于PriorityBlockingQueue,以下代码运行结果是什么(答案往下拉)?
BlockingQueuequeue = new PriorityBlockingQueue<>(2); queue.put(9); queue.put(1); queue.put(8); System.out.println("queue.size() = " + queue.size()); System.out.println("queue.take() = " + queue.take()); System.out.println("queue = " + queue);
2、关于 SynchronousQueue,以下代码运行结果是什么(答案往下拉)?
BlockingQueuequeue = new SynchronousQueue<>(); System.out.println("queue.offer(1) = " + queue.offer(1)); System.out.println("queue.offer(2) = " + queue.offer(2)); System.out.println("queue.offer(3) = " + queue.offer(3)); System.out.println("queue.size = " + queue.size()); System.out.println("queue.take() = " + queue.take());
3、总体测试,以下代码运行结果是什么(答案往下拉)?
offer(new ArrayBlockingQueue<>(2)); offer(new LinkedBlockingQueue<>(2)); offer(new PriorityBlockingQueue<>(2)); offer(new SynchronousQueue<>());
private static void offer(BlockingQueuequeue) throws Exception { System.out.println("queue.getClass() = " + queue.getClass().getName()); System.out.println("queue.offer(1) = " + queue.offer(1)); System.out.println("queue.offer(2) = " + queue.offer(2)); System.out.println("queue.offer(3) = " + queue.offer(3)); System.out.println("queue.size() = " + queue.size()); System.out.println("queue.take() = " + queue.take()); }
下面公布答案:
1、关于PriorityBlockingQueue 运行结果:
原因:
(1).PriorityBlockingQueue put(Object) 方法不阻塞,内部直接调用 offer(Object) 方法 (2).PriorityBlockingQueue offer(Object) 方法不限制,初始化Queue大小是没用的 (3).PriorityBlockingQueue 插入对象会做排序,默认参照元素 Comparable 实现,或者显示地传递 Comparator(因为传入对象是Integer,是默认实现了Comparable的)
2、关于 SynchronousQueue 运行结果
原因:
(1).SynchronousQueue 是无空间,offer 永远返回 false (2).SynchronousQueue take() 方法会被阻塞,必须被其他线程显示地调用 put(Object)
如果第1题、第2题你的回答都有问题,那么总结一下,再看第3题的答案吧
3、总体测试,运行结果
总体而言,BlockingQueue 最让人想不到的就是 PriorityBlockingQueue 和 SynchronousQueue 了。
总结一下:
(1)ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,FIFO(先进先出)。
(2)LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO (先进先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue,静态工厂方法 Executors.newFixedThreadPool() 使用了这个队列。
(3)SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法 Executors.newCachedThreadPool() 使用了这个队列。
(4)PriorityBlockingQueue:一个具有优先级的无限阻塞队列。
本文有参考小马哥的讲课。