最近學習了 BlockingQueue,發現 java 的 BlockingQueue 並不是每一個實現都按照 BlockingQueue 的語意來的,其中有不少坑。
直接上代碼吧:
1、關於PriorityBlockingQueue,以下代碼運行結果是什么(答案往下拉)?
BlockingQueue<Integer> queue = 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,以下代碼運行結果是什么(答案往下拉)?
BlockingQueue<Integer> queue = 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(BlockingQueue<Integer> queue) 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:一個具有優先級的無限阻塞隊列。
本文有參考小馬哥的講課。