有時候,我們有一些任務需要「稍後」來做,比如一些連線需要空閒一段時間後再關閉,session需要空閒一段時間後自動退出。這個時候就需要一些可以延遲執行任務的工具。delayqueue
(延遲佇列)就是乙個可以實現類似功能的工具。
由於本篇會涉及到優先佇列priorityqueue
,所以預先閱讀 深度解析優先順序佇列priorityqueue 很有必要。
delayqueue
(延遲佇列)的標準實現出現在jdk1.5中的j.u.c包中,作為乙個工具類,用來管理一些需要延遲處理的任務。先來看下它的類體系結構:
需要注意的是delayqueue
實現了blockingqueue
介面,意味著它也是阻塞佇列,但是類名稱中沒有包含blocking
因為delayqueue
比一般佇列使用起來稍微複雜一定,所以先看乙個例項:
/**
* @author sicimike
*/public class delayqueuedemo catch (interruptedexception e) }}
}
其中佇列內部元素delayobject
定義如下:
/**
* 延遲佇列中的元素
* 必須實現delayed介面
* @author sicimike
*/class delayobject implements delayed
@override
public int compareto(delayed o)
public delayobject()
public delayobject(string id, long destroytime)
public long getdestroytime()
public void setdestroytime(long destroytime)
public string getid()
public void setid(string id)
@override
public string tostring() ';}}
執行結果:
1576763926966 -> 入隊完成
1576763929959 -> delayobject
1576763932959 -> delayobject
1576763934961 -> delayobject
從執行結果可以看出,三個元素入隊完成後,大概延遲了3秒,出隊了第乙個元素;繼續延遲3秒,出隊第二個元素;繼續延遲2秒,出隊第三個元素。
元素的出隊順序與放入的順序無關,而與元素延遲的時間有關,按照公升序排列出隊,順序由delayobject
中的compareto
方法決定。
放入delayqueue
中的元素必須實現delayed
介面,實現介面中的getdelay
方法和compareto
方法。getdelay
獲取的是元素剩餘的時間,所以不同的時刻呼叫該方法,應該得到不同的值,否則元素永遠不會過期。compareto
方法用於給元素排序,排在前面的先出隊。
這就是延遲佇列delayqueue
的基本使用。
大致了解delayqueue
的使用後,再來看下delayqueue
是如何實現的。首先就要看它的類定義和成員變數
public class delayqueueextends abstractqueueimplements blockingqueue
根據定義可以看出底層通過組合的方式持有優先佇列priorityqueue
的物件,也就是說延遲佇列delayqueue
底層是通過優先佇列priorityqueue
來實現的。
需要重點關注的核心操作只有三個:入隊、出隊、檢視隊首元素。
offer(e e)
方法用於往delayqueue
中放入元素。由於delayqueue
是無界佇列(底層priorityqueue
可以自動擴容),所以往delayqueue
中放入元素是非阻塞的。put
、add
均是呼叫offer
方法,其實現如下:
public void put(e e)
public boolean add(e e)
public boolean offer(e e, long timeout, timeunit unit)
// 真正完成入隊操作的方法
public boolean offer(e e)
return true;
} finally
}
take()
方法以阻塞的方式從delayqueue
中取出乙個元素。
public e take() throws interruptedexception finally }}
}} finally
}
通過take
方法可以看出delayqueue
使用reentrantlock
+condition
來實現執行緒的阻塞、喚醒。再加上迴圈,如果隊首元素不出隊,執行緒會一直被阻塞。
這裡的leader使用的是leader/follower
模型,隊首元素尚未出隊時,leader不為null。其餘的執行緒知道leader不為null之後就被無限阻塞;隊首元素出隊後,leader為null,通知其餘的執行緒來爭搶。
delayqueue
實現了blockingqueue
介面,是阻塞佇列。底層利用了優先佇列priorityqueue
的自動擴容、排序等機制。再利用reentrantlock
+condition
機制實現執行緒安全,以及執行緒休眠、喚醒。
深度解析佇列操作
大家都知道,佇列是一種特殊的線性表,是運算受到限制的一種線性表,只允許在表的一端進行插入,而在另一端進行刪除元素的線性表。隊尾 tail 是允許插入的一端。隊頭 head 是允許刪除的一端。空佇列是不含元素的空表。根據這樣的操作。佇列特點是先進先出 通過此篇,你將會深入了解到佇列的基本操作,便於以後...
Rabbitmq延遲佇列
建立乙個自定義列表 如何建立乙個註腳 注釋也是必不可少的 katex數學公式 新的甘特圖功能,豐富你的文章 uml 圖表 flowchart流程圖 匯出與匯入 你好!這是你第一次使用markdown編輯器所展示的歡迎頁。如果你想學習如何使用markdown編輯器,可以仔細閱讀這篇文章,了解一下mar...
延遲佇列 redis
三 缺點 總結延遲佇列的實現方式有多種,這裡用redis 的zset 來實現 使用 zset 思路 我們給每個value設定score 過期時間的時間戳 例如 當前時間戳是 1609154995707 60秒後過期,則可以設定score 1609154995707 60 然後倒序排列,每次取出一批過...