1. 程式人生 > >記錄 Java 的 BlockingQueue 中的一些坑

記錄 Java 的 BlockingQueue 中的一些坑

最近學習了 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:一個具有優先順序的無限阻塞佇列。

本文有參考小馬哥的講課。

&n