摘要:如果延遲都還沒有期滿,則隊列沒有頭部,此時調(diào)用將直接返回,調(diào)用將會發(fā)生阻塞,直到有元素發(fā)生到期,才會返回。比如,此元素還有毫秒延時期滿傳入的參數(shù)為那么返回值為,即兩秒。
DelayQueue簡介
DelayQueue是juc包中的類,它表示的是一個無界的延遲隊列,定義如下:
public class DelayQueueextends AbstractQueue implements BlockingQueue ;
DelayQueue存儲的元素需要實現(xiàn)Delayed接口以實現(xiàn)優(yōu)先級比較和延時取得。
DelayQueue還是一個阻塞隊列,只有在延遲期滿時才能從中提取元素。該隊列的頭部是延遲期滿后保存時間最長的 Delayed 元素。如果延遲都還沒有期滿,則隊列沒有頭部,此時調(diào)用 poll() 將直接返回 null,調(diào)用 take() 將會發(fā)生阻塞,直到有元素發(fā)生到期,take() 才會返回。
場景應(yīng)用當(dāng)一個元素的 getDelay() 方法返回一個小于等于 0 的值時,將發(fā)生到期。
下面將使用此類實現(xiàn)一個多考生考試的場景:
考試總時間為10秒,至少2秒后才可進行交卷。
考生可在2-10秒這段時間內(nèi)的任意時間交卷。
考試時間一到,所有未交卷的學(xué)生必須交卷。
注:上述時間數(shù)據(jù)僅為測試方便使用,可根據(jù)實際情況進行修改
使用enum定義出時間常量:
enum Times { SUMMIT_TIME(10), //考試總時間 SUMBMIT_LIMIT(2), // 交卷限制時間 MAX_RAND_TIME(15); // 模擬考生所需最大時間 private final int value; private Times(int value) { this.value = value; } public int getValue() { return value; } }定義學(xué)生類
基本定義:
class Student implements Delayed { private String name; private long delay; // 考試花費時間,單位為毫秒 private long expire; // 交卷時間,單位為毫秒 // 此構(gòu)造可隨機生成考試花費時間 public Student(String name) { this.name = name; this.delay = TimeUnit.MILLISECONDS.convert(getRandomSeconds(), TimeUnit.SECONDS); this.expire = System.currentTimeMillis() + this.delay; } //此構(gòu)造可指定考試花費時間 public Student(String name, long delay, TimeUnit unit) { this.name = name; this.delay = TimeUnit.MILLISECONDS.convert(delay, unit); this.expire = System.currentTimeMillis() + this.delay; } // ... }
利用Random獲取學(xué)生考試花費時間:
public int getRandomSeconds() { // 獲取隨機花費時間,范圍:2-10秒 return new Random().nextInt(Times.MAX_RAND_TIME.getValue() - Times.SUMBMIT_LIMIT.getValue()) + Times.SUMBMIT_LIMIT.getValue(); }
覆寫的compareTo()和getDelay()方法:
其中,getDelay()方法根據(jù)傳入的TimeUnit返回剩余延時。比如,此元素還有2000毫秒延時期滿、傳入的參數(shù)為TimeUnit.SECONDS,那么返回值為2,即兩秒。
@Override public int compareTo(Delayed o) { // 此方法的實現(xiàn)用于定義優(yōu)先級 long td = this.getDelay(TimeUnit.MILLISECONDS); long od = o.getDelay(TimeUnit.MILLISECONDS); return td > od ? 1 : td == od ? 0 : -1; } @Override public long getDelay(TimeUnit unit) { // 這里返回的是剩余延時,當(dāng)延時為0時,此元素延時期滿,可從take()取出 return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS); }主方法實現(xiàn)
初始化對象
DelayQueuequeue = new DelayQueue<>();
添加測試數(shù)據(jù)
queue.add(new Student("范冰冰")); queue.add(new Student("成 龍")); queue.add(new Student("李一桐")); queue.add(new Student("宋小寶")); queue.add(new Student("吳 京")); queue.add(new Student("綠巨人")); queue.add(new Student("洪金寶")); queue.add(new Student("李云龍")); queue.add(new Student("鋼鐵俠")); queue.add(new Student("劉德華")); queue.add(new Student("戴安娜"));
添加一條用于考試結(jié)束時強制交卷的屬性
queue.add(new Student("submit", Times.SUBMIT_TIME.getValue(),TimeUnit.SECONDS));
開始考試
while (true) { Student s = queue.take(); // 必要時進行阻塞等待 if (s.getName().equals("submit")) { System.out.println("時間已到,全部交卷!"); // 利用Java8 Stream特性使尚未交卷學(xué)生交卷 queue.parallelStream() .filter(v -> v.getExpire() >= s.getExpire()) .map(Student::submit) .forEach(System.out::println); System.exit(0); } System.out.println(s); }輸出樣例 完整代碼
package cn.gss.juc; import java.text.DateFormat; import java.util.Date; import java.util.Random; import java.util.concurrent.DelayQueue; import java.util.concurrent.Delayed; import java.util.concurrent.TimeUnit; enum Times { SUBMIT_TIME(10), SUMBMIT_LIMIT(2), MAX_RAND_TIME(15); private final int value; private Times(int value) { this.value = value; } public int getValue() { return value; } } /** * DelayQueue實現(xiàn)多考生考試 * @author Gss */ public class TestDelayedQueue { public static void main(String[] args) throws InterruptedException { DelayQueuequeue = new DelayQueue<>(); queue.add(new Student("范冰冰")); queue.add(new Student("成 龍")); queue.add(new Student("李一桐")); queue.add(new Student("宋小寶")); queue.add(new Student("吳 京")); queue.add(new Student("綠巨人")); queue.add(new Student("洪金寶")); queue.add(new Student("李云龍")); queue.add(new Student("鋼鐵俠")); queue.add(new Student("劉德華")); queue.add(new Student("戴安娜")); queue.add(new Student("submit", Times.SUBMIT_TIME.getValue(), TimeUnit.SECONDS)); while (true) { Student s = queue.take(); // 必要時進行阻塞等待 if (s.getName().equals("submit")) { System.out.println("時間已到,全部交卷!"); // 利用Java8 Stream使尚未交卷學(xué)生交卷 queue.parallelStream() .filter(v -> v.getExpire() >= s.getExpire()) .map(Student::submit) .forEach(System.out::println); System.exit(0); } System.out.println(s); } } } class Student implements Delayed { private String name; private long delay; // 考試花費時間,單位為毫秒 private long expire; // 交卷時間,單位為毫秒 // 此構(gòu)造可隨機生成考試花費時間 public Student(String name) { this.name = name; this.delay = TimeUnit.MILLISECONDS.convert(getRandomSeconds(), TimeUnit.SECONDS); // 隨機生成考試花費時間 this.expire = System.currentTimeMillis() + this.delay; } // 此構(gòu)造可指定考試花費時間 public Student(String name, long delay, TimeUnit unit) { this.name = name; this.delay = TimeUnit.MILLISECONDS.convert(delay, unit); this.expire = System.currentTimeMillis() + this.delay; } public int getRandomSeconds() { // 獲取隨機花費時間 return new Random().nextInt(Times.MAX_RAND_TIME.getValue() - Times.SUMBMIT_LIMIT.getValue()) + Times.SUMBMIT_LIMIT.getValue(); } public Student submit() { // 設(shè)置花費時間和交卷時間,考試時間結(jié)束強制交卷時調(diào)用此方法 setDelay(Times.SUBMIT_TIME.getValue(), TimeUnit.SECONDS); setExpire(System.currentTimeMillis()); return this; } public String getName() { return name; } public long getExpire() { return expire; } public void setDelay(long delay, TimeUnit unit) { this.delay = TimeUnit.MILLISECONDS.convert(delay, TimeUnit.SECONDS); } public void setExpire(long expire) { this.expire = expire; } @Override public int compareTo(Delayed o) { // 此方法的實現(xiàn)用于定義優(yōu)先級 long td = this.getDelay(TimeUnit.MILLISECONDS); long od = o.getDelay(TimeUnit.MILLISECONDS); return td > od ? 1 : td == od ? 0 : -1; } @Override public long getDelay(TimeUnit unit) { // 這里返回的是剩余延時,當(dāng)延時為0時,此元素延時期滿,可從take()取出 return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS); } @Override public String toString() { return "學(xué)生姓名:" + this.name + ",考試用時:" + TimeUnit.SECONDS.convert(delay, TimeUnit.MILLISECONDS) + ",交卷時間:" + DateFormat.getDateTimeInstance().format(new Date(this.expire)); } }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/70500.html
摘要:線程池任務(wù)隊列構(gòu)造方法,實例化時啟動線程設(shè)置任務(wù)隊列,用于任務(wù)重新入隊任務(wù)入隊從延遲隊列中獲取任務(wù)利用線程池執(zhí)行任務(wù)實現(xiàn)了接口,執(zhí)行實際的業(yè)務(wù)并決定任務(wù)是否重新進入延遲隊列。 前言 接入微信支付的時候,看到微信支付的回調(diào)是按照某種頻率去回調(diào)的,像15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h這樣,其中有一次成功就不會再回調(diào)。于...
摘要:今天給大家介紹下周期性線程池的使用和重點源碼剖析。用來處理延時任務(wù)或定時任務(wù)定時線程池類的類結(jié)構(gòu)圖接收類型的任務(wù),是線程池調(diào)度任務(wù)的最小單位。周期性線程池任務(wù)的提交方式周期性有三種提交的方式。 之前學(xué)習(xí)ThreadPool的使用以及源碼剖析,并且從面試的角度去介紹知識點的解答。今天給大家介紹下周期性線程池的使用和重點源碼剖析。 ScheduledThreadPoolExecutor S...
摘要:請考生務(wù)必妥善保管個人網(wǎng)報用戶名密碼及準(zhǔn)考證居民身份證等證件,避免泄露丟失造成損失。自主劃線院校會在月陸續(xù)公布初試成績基本要求。鎖定時間到達后,如招生單位未明確受理意見,鎖定解除,考生可繼續(xù)填報其他志愿。 ...
摘要:怎樣讓程序代碼行更少,怎樣用更嚴(yán)謹(jǐn)?shù)倪壿嫓p少錯誤發(fā)生,怎樣讓用戶體驗更好,并不斷學(xué)習(xí),著手解決現(xiàn)有的問題,這就是編程大佬的日常。認(rèn)證報名不受年齡職業(yè)學(xué)歷等限制,可根據(jù)自己的能力情況從到級別進行選擇測評考試。 自查 自學(xué) 自省 計算機行業(yè)永遠沒有全知全能一說,開發(fā)者的水平再高,也不可能躺在功勞...
閱讀 2158·2021-09-22 10:56
閱讀 1465·2021-09-07 10:11
閱讀 1801·2019-08-30 15:54
閱讀 2290·2019-08-30 15:44
閱讀 2307·2019-08-29 12:40
閱讀 3031·2019-08-28 18:25
閱讀 1735·2019-08-26 10:24
閱讀 3186·2019-08-23 18:39