詳解Java線程池隊列中的延遲隊列DelayQueue
在阻塞隊里中,除了對元素進行增加和刪除外,我們可以把元素的刪除做一個延遲的處理,即使用DelayQueue的方法。本文就來和大家聊聊Java線程池隊列中的DelayQueue—延遲隊列
public enum QueueTypeEnum { ARRAY_BLOCKING_QUEUE(1, "ArrayBlockingQueue"), LINKED_BLOCKING_QUEUE(2, "LinkedBlockingQueue"), DELAY_QUEUE(3, "DelayQueue"), PRIORITY_BLOCKING_QUEUE(4, "PriorityBlockingQueue"), SYNCHRONOUS_QUEUE(5, "SynchronousQueue"), LINKED_TRANSFER_QUEUE(6, "LinkedTransferQueue"), LINKED_BLOCKING_DEQUE(7, "LinkedBlockingDeque"), VARIABLE_LINKED_BLOCKING_QUEUE(8, "VariableLinkedBlockingQueue"), MEMORY_SAFE_LINKED_BLOCKING_QUEUE(9, "MemorySafeLinkedBlockingQueue"); }
DelayQueue延遲隊列
類似于PriorityBlockingQueue,是二叉堆實現的無界優(yōu)先級阻塞隊列。要求元素都實現Delayed 接口,通過執(zhí)行時延從隊列中提取任務,只有在延遲期滿后才能從中提取元素。DelayQueue的泛型參數需要實現Delayed接口,Delayed接口繼承了Comparable接口,DelayQueue內部使用非線程安全的優(yōu)先隊列(PriorityQueue),并使用Leader/Followers模式,最小化不必要的等待時間。DelayQueue不允許包含null元素。
public interface Delayed extends Comparable<Delayed> { /** * 返回與此對象關聯的剩余延遲(給定的時間單位)。 * @param unit 時間單位 * @返回剩余延遲;零值或負值表示 延遲已過期 */ long getDelay(TimeUnit unit); }
DelayQueue使用場景
緩存系統(tǒng)的設計:可以用DelayQueue保存緩存元素的有效期,使用一個線程循環(huán)查詢DelayQueue,一旦能從DelayQueue中獲取元素時,表示緩存有效期到了。
定時任務調度:使用DelayQueue保存當天將會執(zhí)行的任務和執(zhí)行時間,一旦從DelayQueue中獲取到任務就開始執(zhí)行,從比如TimerQueue就是使用DelayQueue實現的。
DelayQueue屬性
//可重入同步鎖 private final transient ReentrantLock lock = new ReentrantLock(); //DelayQueue的實現依賴于PriorityQueue(優(yōu)先隊列) private final PriorityQueue<E> q = new PriorityQueue<E>(); //第一個等待某個延時對象的線程,在延時對象還沒有到期時其他線程看到這個leader不為null,那么就直接wait //主要是為了避免大量線程在同一時間點喚醒,導致大量的競爭,反而影響性能 private Thread leader = null; //條件隊列,用于wait線程 private final Condition available = lock.newCondition();
DelayQueue構造方法
//從上面屬性就可以看出,DelayQueue采用了餓漢模式,調用構造方法即創(chuàng)建了隊列實例 public DelayQueue() {} /** * 創(chuàng)建一個DelayQueue,最初包含給定的Collection實例集合。 * @param c 最初包含的元素集合 */ public DelayQueue(Collection<? extends E> c) { this.addAll(c); }
實現Delayed接口使用示例
class MyDelay<T> implements Delayed { long delayTime; // 延遲時間 long expire; // 過期時間 T data; public MyDelay(long delayTime, T t) { this.delayTime = delayTime; // 過期時間 = 當前時間 + 延遲時間 this.expire = System.currentTimeMillis() + delayTime; data = t; } /** * 剩余時間 = 到期時間 - 當前時間 */ @Override public long getDelay(TimeUnit unit) { return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS); } /** * 優(yōu)先級規(guī)則:兩個任務比較,時間短的優(yōu)先執(zhí)行 */ @Override public int compareTo(Delayed o) { long f = this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS); return (int) f; } @Override public String toString() { return "delayTime=" + delayTime + ", expire=" + expire + ", data=" + data; } } public class DelayQueueDemo { static BlockingQueue<Delayed> queue = new DelayQueue(); public static void main(String[] args) throws InterruptedException { queue.add(new MyDelay(8, "第一次添加任務")); queue.add(new MyDelay(3, "第二次添加任務")); queue.add(new MyDelay(5, "第三次添加任務")); while (!queue.isEmpty()) { Delayed delayed = queue.take(); System.out.println(delayed); } } }
DelayQueue總結
DelayQueue其實采用了裝飾器模式,在對PriorityQueue進行包裝下增加了延時時間獲取元素的功能,其主要特點歸納如下:
- DelayQueue是一個無界阻塞隊列,隊列內部使用PriorityQueue來實現
- 進入隊列的元素必須實現Delayed接口,在創(chuàng)建元素時可以指定多久才能從隊列中獲取當前元素,只有在延遲期滿時才能從中提取元素
- 該隊列頭部是延遲期滿后保存時間最長的Delayed元素
- 如果沒有延遲未過期元素,且隊列沒有頭部,并且poll將返回null
- 當一個元素的getDelay(TimeUnit.NANOSECONDS)方法返回一個小于等于0的值時,表示該元素已過期
- 無法使用poll或take移除未到期的元素,也不會將這些元素作為正常元素對待;例如:size方法返回到期和未到期元素的計數之和
- 此隊列不允許使用null元素
到此這篇關于詳解Java線程池隊列中的延遲隊列DelayQueue的文章就介紹到這了,更多相關Java延遲隊列DelayQueue內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java如何使用httpclient檢測url狀態(tài)及鏈接是否能打開
這篇文章主要介紹了Java如何使用httpclient檢測url狀態(tài)及鏈接是否能打開,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09Java使用Apache compress實現文件夾壓縮成Zip包
Apache common提供了很多實用的工具包,這篇文章主要來和大家介紹一下Java如何使用Apache compress包實現文件夾壓縮成Zip包,希望對大家有所幫助2024-01-01IntelliJ?IDEA運行SpringBoot項目的詳細步驟
這篇文章主要介紹了IntelliJ?IDEA如何運行SpringBoot項目,步驟一配置maven,步驟二配置JDK環(huán)境,緊接著通過步驟三檢查數據庫的配置,最后一步數據庫連接,本文給大家介紹的非常詳細,需要的朋友可以參考下2022-08-08Spring Data JPA 整合QueryDSL的使用案例
QueryDSL 是一個用于構建類型安全的 SQL 查詢的 Java 庫,它的主要目標是簡化在 Java 中構建和執(zhí)行 SQL 查詢的過程,同時提供類型安全性和更好的編碼體驗,對Spring Data JPA 整合QueryDSL使用案例感興趣的朋友跟隨小編一起看看吧2023-08-08