記錄 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:一個具有優先級的無限阻塞隊列。

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM