DelayQueue是juc包中的類,它表示的是一個無界的延遲隊列,定義以下:java
public class DelayQueue<E extends Delayed> extends AbstractQueue<E> implements BlockingQueue<E>;
DelayQueue存儲的元素須要實現Delayed接口以實現優先級比較和延時取得。dom
DelayQueue仍是一個阻塞隊列,只有在延遲期滿時才能從中提取元素。該隊列的頭部是延遲期滿後保存時間最長的 Delayed 元素。若是延遲都尚未期滿,則隊列沒有頭部,此時調用 poll() 將直接返回 null,調用 take() 將會發生阻塞,直到有元素髮生到期,take() 纔會返回。ide
當一個元素的 getDelay() 方法返回一個小於等於 0 的值時,將發生到期。測試
下面將使用此類實現一個多考生考試的場景:this
注:上述時間數據僅爲測試方便使用,可根據實際狀況進行修改spa
使用enum定義出時間常量:3d
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; } }
基本定義:code
class Student implements Delayed { private String name; private long delay; // 考試花費時間,單位爲毫秒 private long expire; // 交卷時間,單位爲毫秒 // 此構造可隨機生成考試花費時間 public Student(String name) { this.name = name; this.delay = TimeUnit.MILLISECONDS.convert(getRandomSeconds(), TimeUnit.SECONDS); this.expire = System.currentTimeMillis() + this.delay; } //此構造可指定考試花費時間 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獲取學生考試花費時間:orm
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()方法根據傳入的TimeUnit返回剩餘延時。好比,此元素還有2000毫秒延時期滿、傳入的參數爲TimeUnit.SECONDS,那麼返回值爲2,即兩秒。
@Override public int compareTo(Delayed o) { // 此方法的實現用於定義優先級 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) { // 這裏返回的是剩餘延時,當延時爲0時,此元素延時期滿,可從take()取出 return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS); }
初始化對象
DelayQueue<Student> queue = 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特性使還沒有交卷學生交卷 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實現多考生考試 * @author Gss */ public class TestDelayedQueue { public static void main(String[] args) throws InterruptedException { DelayQueue<Student> queue = 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使還沒有交卷學生交卷 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; // 交卷時間,單位爲毫秒 // 此構造可隨機生成考試花費時間 public Student(String name) { this.name = name; this.delay = TimeUnit.MILLISECONDS.convert(getRandomSeconds(), TimeUnit.SECONDS); // 隨機生成考試花費時間 this.expire = System.currentTimeMillis() + this.delay; } // 此構造可指定考試花費時間 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() { // 設置花費時間和交卷時間,考試時間結束強制交卷時調用此方法 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) { // 此方法的實現用於定義優先級 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) { // 這裏返回的是剩餘延時,當延時爲0時,此元素延時期滿,可從take()取出 return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS); } @Override public String toString() { return "學生姓名:" + this.name + ",考試用時:" + TimeUnit.SECONDS.convert(delay, TimeUnit.MILLISECONDS) + ",交卷時間:" + DateFormat.getDateTimeInstance().format(new Date(this.expire)); } }