您好,登錄后才能下訂單哦!
今天小編給大家分享一下Java線程池隊(duì)列中的延遲隊(duì)列DelayQueue怎么使用的相關(guān)知識點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
在阻塞隊(duì)里中,除了對元素進(jìn)行增加和刪除外,我們可以把元素的刪除做一個(gè)延遲的處理,即使用DelayQueue的方法。本文就來和大家聊聊Java線程池隊(duì)列中的DelayQueue—延遲隊(duì)列
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"); }
類似于PriorityBlockingQueue,是二叉堆實(shí)現(xiàn)的無界優(yōu)先級阻塞隊(duì)列。要求元素都實(shí)現(xiàn)Delayed 接口,通過執(zhí)行時(shí)延從隊(duì)列中提取任務(wù),只有在延遲期滿后才能從中提取元素。DelayQueue的泛型參數(shù)需要實(shí)現(xiàn)Delayed接口,Delayed接口繼承了Comparable接口,DelayQueue內(nèi)部使用非線程安全的優(yōu)先隊(duì)列(PriorityQueue),并使用Leader/Followers模式,最小化不必要的等待時(shí)間。DelayQueue不允許包含null元素。
public interface Delayed extends Comparable<Delayed> { /** * 返回與此對象關(guān)聯(lián)的剩余延遲(給定的時(shí)間單位)。 * @param unit 時(shí)間單位 * @返回剩余延遲;零值或負(fù)值表示 延遲已過期 */ long getDelay(TimeUnit unit); }
緩存系統(tǒng)的設(shè)計(jì):可以用DelayQueue保存緩存元素的有效期,使用一個(gè)線程循環(huán)查詢DelayQueue,一旦能從DelayQueue中獲取元素時(shí),表示緩存有效期到了。
定時(shí)任務(wù)調(diào)度:使用DelayQueue保存當(dāng)天將會執(zhí)行的任務(wù)和執(zhí)行時(shí)間,一旦從DelayQueue中獲取到任務(wù)就開始執(zhí)行,從比如TimerQueue就是使用DelayQueue實(shí)現(xiàn)的。
//可重入同步鎖 private final transient ReentrantLock lock = new ReentrantLock(); //DelayQueue的實(shí)現(xiàn)依賴于PriorityQueue(優(yōu)先隊(duì)列) private final PriorityQueue<E> q = new PriorityQueue<E>(); //第一個(gè)等待某個(gè)延時(shí)對象的線程,在延時(shí)對象還沒有到期時(shí)其他線程看到這個(gè)leader不為null,那么就直接wait //主要是為了避免大量線程在同一時(shí)間點(diǎn)喚醒,導(dǎo)致大量的競爭,反而影響性能 private Thread leader = null; //條件隊(duì)列,用于wait線程 private final Condition available = lock.newCondition();
//從上面屬性就可以看出,DelayQueue采用了餓漢模式,調(diào)用構(gòu)造方法即創(chuàng)建了隊(duì)列實(shí)例 public DelayQueue() {} /** * 創(chuàng)建一個(gè)DelayQueue,最初包含給定的Collection實(shí)例集合。 * @param c 最初包含的元素集合 */ public DelayQueue(Collection<? extends E> c) { this.addAll(c); }
class MyDelay<T> implements Delayed { long delayTime; // 延遲時(shí)間 long expire; // 過期時(shí)間 T data; public MyDelay(long delayTime, T t) { this.delayTime = delayTime; // 過期時(shí)間 = 當(dāng)前時(shí)間 + 延遲時(shí)間 this.expire = System.currentTimeMillis() + delayTime; data = t; } /** * 剩余時(shí)間 = 到期時(shí)間 - 當(dāng)前時(shí)間 */ @Override public long getDelay(TimeUnit unit) { return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS); } /** * 優(yōu)先級規(guī)則:兩個(gè)任務(wù)比較,時(shí)間短的優(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, "第一次添加任務(wù)")); queue.add(new MyDelay(3, "第二次添加任務(wù)")); queue.add(new MyDelay(5, "第三次添加任務(wù)")); while (!queue.isEmpty()) { Delayed delayed = queue.take(); System.out.println(delayed); } } }
DelayQueue其實(shí)采用了裝飾器模式,在對PriorityQueue進(jìn)行包裝下增加了延時(shí)時(shí)間獲取元素的功能,其主要特點(diǎn)歸納如下:
DelayQueue是一個(gè)無界阻塞隊(duì)列,隊(duì)列內(nèi)部使用PriorityQueue來實(shí)現(xiàn)
進(jìn)入隊(duì)列的元素必須實(shí)現(xiàn)Delayed接口,在創(chuàng)建元素時(shí)可以指定多久才能從隊(duì)列中獲取當(dāng)前元素,只有在延遲期滿時(shí)才能從中提取元素
該隊(duì)列頭部是延遲期滿后保存時(shí)間最長的Delayed元素
如果沒有延遲未過期元素,且隊(duì)列沒有頭部,并且poll將返回null
當(dāng)一個(gè)元素的getDelay(TimeUnit.NANOSECONDS)方法返回一個(gè)小于等于0的值時(shí),表示該元素已過期
無法使用poll或take移除未到期的元素,也不會將這些元素作為正常元素對待;例如:size方法返回到期和未到期元素的計(jì)數(shù)之和
此隊(duì)列不允許使用null元素
以上就是“Java線程池隊(duì)列中的延遲隊(duì)列DelayQueue怎么使用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。