java加载c库阻塞_【死磕Java並發】-----J.U.C之阻塞隊列:BlockingQueue總結

經過前面六篇博客的闡述,我想各位應該對阻塞隊列BlockingQueue有了較為深入的理解,下面來一個總結,先看整個類圖:

aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTcxMDA0MTgyMzMwODkzP3dhdGVybWFyay8yL3RleHQvYUhSMGNEb3ZMMkpzYjJjdVkzTmtiaTV1WlhRdlkyaGxibk56ZVE9PS9mb250LzVhNkw1TDJUL2ZvbnRzaXplLzQwMC9maWxsL0kwSkJRa0ZDTUE9PS9kaXNzb2x2ZS83MC9ncmF2aXR5L1NvdXRoRWFzdA==

BlockingQueue

BlockingQueue接口實現Queue接口,它支持兩個附加操作:獲取元素時等待隊列變為非空,以及存儲元素時等待空間變得可用。相對於同一操作他提供了四種機制:拋出異常、返回特殊值、阻塞等待、超時:

aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTcxMDA0MTgyNDAzMjE0P3dhdGVybWFyay8yL3RleHQvYUhSMGNEb3ZMMkpzYjJjdVkzTmtiaTV1WlhRdlkyaGxibk56ZVE9PS9mb250LzVhNkw1TDJUL2ZvbnRzaXplLzQwMC9maWxsL0kwSkJRa0ZDTUE9PS9kaXNzb2x2ZS83MC9ncmF2aXR5L1NvdXRoRWFzdA==

BlockingQueue常用於生產者和消費者場景。

JDK 8 中提供了七個阻塞隊列可供使用(上圖的DelayedWorkQueue是ScheduledThreadPoolExecutor的內部類):

ArrayBlockingQueue :一個由數組結構組成的有界阻塞隊列。

LinkedBlockingQueue :一個由鏈表結構組成的無界阻塞隊列。

PriorityBlockingQueue :一個支持優先級排序的無界阻塞隊列。

DelayQueue:一個使用優先級隊列實現的無界阻塞隊列。

SynchronousQueue:一個不存儲元素的阻塞隊列。

LinkedTransferQueue:一個由鏈表結構組成的無界阻塞隊列。

LinkedBlockingDeque:一個由鏈表結構組成的雙向阻塞隊列。

ArrayBlockingQueue

基於數組的阻塞隊列,ArrayBlockingQueue內部維護這一個定長數組,阻塞隊列的大小在初始化時就已經確定了,其后無法更改。

采用可重入鎖ReentrantLock來保證線程安全性,但是生產者和消費者是共用同一個鎖對象,這樣勢必會導致降低一定的吞吐量。當然ArrayBlockingQueue完全可以采用分離鎖來實現生產者和消費者的並行操作,但是我認為這樣做只會給代碼帶來額外的復雜性,對於性能而言應該不會有太大的提升,因為基於數組的ArrayBlockingQueue在數據的寫入和讀取操作已經非常輕巧了。

ArrayBlockingQueue支持公平性和非公平性,默認采用非公平模式,可以通過構造函數設置為公平訪問策略(true)。

PriorityBlockingQueue

PriorityBlockingQueue是支持優先級的無界隊列。默認情況下采用自然順序排序,當然也可以通過自定義Comparator來指定元素的排序順序。

PriorityBlockingQueue內部采用二叉堆的實現方式,整個處理過程並不是特別復雜。添加操作則是不斷“上冒”,而刪除操作則是不斷“下掉”。

DelayQueue

DelayQueue是一個支持延時操作的無界阻塞隊列。列頭的元素是最先“到期”的元素,如果隊列里面沒有元素到期,是不能從列頭獲取元素的,哪怕有元素也不行。也就是說只有在延遲期滿時才能夠從隊列中去元素。

它主要運用於如下場景:

緩存系統的設計:緩存是有一定的時效性的,可以用DelayQueue保存緩存的有效期,然后利用一個線程查詢DelayQueue,如果取到元素就證明該緩存已經失效了。

定時任務的調度:DelayQueue保存當天將要執行的任務和執行時間,一旦取到元素(任務),就執行該任務。

DelayQueue采用支持優先級的PriorityQueue來實現,但是隊列中的元素必須要實現Delayed接口,Delayed接口用來標記那些應該在給定延遲時間之后執行的對象,該接口提供了getDelay()方法返回元素節點的剩余時間。同時,元素也必須要實現compareTo()方法,compareTo()方法需要提供與getDelay()方法一致的排序。

SynchronousQueue

SynchronousQueue是一個神奇的隊列,他是一個不存儲元素的阻塞隊列,也就是說他的每一個put操作都需要等待一個take操作,否則就不能繼續添加元素了,有點兒像Exchanger,類似於生產者和消費者進行交換。

隊列本身不存儲任何元素,所以非常適用於傳遞性場景,兩者直接進行對接。其吞吐量會高於ArrayBlockingQueue和LinkedBlockingQueue。

SynchronousQueue支持公平和非公平的訪問策略,在默認情況下采用非公平性,也可以通過構造函數來設置為公平性。

SynchronousQueue的實現核心為Transferer接口,該接口有TransferQueue和TransferStack兩個實現類,分別對應着公平策略和非公平策略。接口Transferer有一個tranfer()方法,該方法定義了轉移數據,如果e != null,相當於將一個數據交給消費者,如果e == null,則相當於從一個生產者接收一個消費者交出的數據。

LinkedTransferQueue

LinkedTransferQueue是一個由鏈表組成的的無界阻塞隊列,該隊列是一個相當牛逼的隊列:它是ConcurrentLinkedQueue、SynchronousQueue (公平模式下)、無界的LinkedBlockingQueues等的超集。

與其他BlockingQueue相比,他多實現了一個接口TransferQueue,該接口是對BlockingQueue的一種補充,多了tryTranfer()和transfer()兩類方法:

tranfer():若當前存在一個正在等待獲取的消費者線程,即立刻移交之。 否則,會插入當前元素e到隊列尾部,並且等待進入阻塞狀態,到有消費者線程取走該元素

tryTranfer(): 若當前存在一個正在等待獲取的消費者線程(使用take()或者poll()函數),使用該方法會即刻轉移/傳輸對象元素e;若不存在,則返回false,並且不進入隊列。這是一個不阻塞的操作

LinkedBlockingDeque

LinkedBlockingDeque是一個有鏈表組成的雙向阻塞隊列,與前面的阻塞隊列相比它支持從兩端插入和移出元素。以first結尾的表示從對頭操作,以last結尾的表示從對尾操作。

在初始化LinkedBlockingDeque時可以初始化隊列的容量,用來防止其再擴容時過渡膨脹。另外雙向阻塞隊列可以運用在“工作竊取”模式中。

擴展閱讀

歡迎掃一掃我的公眾號關注 — 及時得到博客訂閱哦!

–— Java成神之路: 488391811(一起走向Java成神) –—

aHR0cDovL2Ntc2Jsb2dzLmNvbS93cC1jb250ZW50L3Jlc291cmNlcy9pbWcvcXJjb2RlX2Zvcl9naF8zZWM5ZGUxMTM1ZjVfMzQ0LmpwZw==

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值