1. 程式人生 > >Java之集合(十八)DelayQueue

Java之集合(十八)DelayQueue

等待 註釋 實現 null 技術 阻塞 任務 計算 等待隊列

  轉載請註明源出處:http://www.cnblogs.com/lighten/p/7493735.html

1.前言

  本章介紹阻塞隊列DelayQueue,這是一個無界阻塞隊列。其存儲延時的元素,只有延時耗盡元素才能被取出。隊列頭元素就是最先耗盡延時的元素,如果沒有元素耗盡延時,poll操作會返回null。同樣的,該隊列不允許空元素。針對延時的特性,可以用戶定時任務,到達時間就能取出任務執行,設計有時效的緩存,超時就清除。

2.DelayQueue

2.1 數據結構

技術分享

  該類的實現十分簡單,可以說是站在其它類的肩膀上實現的。一個保證線程安全的鎖,一個存儲元素的優先隊列,一個等待隊列頭元素的線程,一個觸發條件。

  優先隊列之前介紹過,隊列頭是比較器或元素自身的比較方法比較出來的最小元素。這個隊列所有的元素都必須實現Delayed接口,其方法需要給出剩余的延時時間。Delayed接口又是實現Comparable接口,註意該優先隊列就是使用這個方法進行對比的,所以Comparable的實現要借助Delayed接口的方法選出剩余延時小,才能保證使用正確。

2.2 基本操作

  放入一個Delayed元素:

技術分享

  線程安全,先加鎖,然後放入一個元素到優先隊列中。嘗試取出,如果還是它,頭元素被替換了,需要重置等待頭元素的線程,喚醒阻塞的線程。

技術分享

  取出元素也先加鎖,嘗試取出,如果時間未到返回null,否則就取出。

技術分享

  超時的poll方法,以納秒計算等待時間。先加鎖保證線程安全,無限循環取第一個元素,如果沒取到並且等待時間耗盡,直接返回null,沒耗盡等待時間就繼續等,直到被可用條件喚醒,或等待超時自動喚醒。如果取到了第一個元素,還需要看其剩余時間是否夠了,夠了就直接返回。不夠等待時間又耗盡了就返回null。如果剩余等待時間比元素滿足條件時間要小或者是有線程在等待第一個元素,直接等下去,等完剩余時間。否則,當前線程就是等待頭元素的線程,可以等到頭元素,等待頭元素的時間。

  整個類的實現並不難,leader線程感覺沒什麽作用,但是按照JDK的註釋所說,這種領導跟隨者模式可以最小化等待的時間。就是說leader線程可以等待下一個延時,其它線程需要無限等待。看代碼其實也能明白,如果存在leader線程,一定是有一個線程在等待第一個元素,那麽本線程就必須一直等,而拿到leader的線程,只需要等第一個元素剩余的延時就可以了。

Java之集合(十八)DelayQueue