DelayQueue的原理和使用淺談

  在談到DelayQueue的使用和原理的時候,咱們首先介紹一下DelayQueue,DelayQueue是一個無界阻塞隊列,只有在延遲期滿時才能從中提取元素。該隊列的頭部是延遲期滿後保存時間最長的Delayed 元素。java

  DelayQueue阻塞隊列在咱們系統開發中也經常會用到,例如:緩存系統的設計,緩存中的對象,超過了空閒時間,須要從緩存中移出;任務調度系統,可以準確的把握任務的執行時間。咱們可能須要經過線程處理不少時間上要求很嚴格的數據,若是使用普通的線程,咱們就須要遍歷全部的對象,一個一個的檢 查看數據是否過時等,首先這樣在執行上的效率不會過高,其次就是這種設計的風格也大大的影響了數據的精度。一個須要12:00點執行的任務可能12:01 才執行,這樣對數據要求很高的系統有更大的弊端。由此咱們能夠使用DelayQueue。緩存

  爲了具備調用行爲,存放到DelayDeque的元素必須繼承Delayed接口。Delayed接口使對象成爲延遲對象,它使存放在DelayQueue類中的對象具備了激活日期。該接口強制執行下列兩個方法。ide

  • CompareTo(Delayed o):Delayed接口繼承了Comparable接口,所以有了這個方法。
  • getDelay(TimeUnit unit):這個方法返回到激活日期的剩餘時間,時間單位由單位參數指定。
public class DelayEvent implements Delayed {
    private Date startDate;
    public DelayEvent(Date startDate) {
        super();
        this.startDate = startDate;
    }
    @Override
    public int compareTo(Delayed o) {
        long result = this.getDelay(TimeUnit.NANOSECONDS)
                - o.getDelay(TimeUnit.NANOSECONDS);
        if (result < 0) {
            return -1;
        } else if (result > 0) {
            return 1;
        } else {
            return 0;
        }
    }
    @Override
    public long getDelay(TimeUnit unit) {
        Date now = new Date();
        long diff = startDate.getTime() - now.getTime();
        return unit.convert(diff, TimeUnit.MILLISECONDS);
    }
}
public class DelayTask implements Runnable {
    private int id;
    private DelayQueue<DelayEvent> queue;
    public DelayTask(int id, DelayQueue<DelayEvent> queue) {
        super();
        this.id = id;
        this.queue = queue;
    }
    @Override
    public void run() {
        Date now = new Date();
        Date delay = new Date();
        delay.setTime(now.getTime() + id * 1000);
        System.out.println("Thread " + id + " " + delay);
        for (int i = 0; i < 100; i++) {
            DelayEvent delayEvent = new DelayEvent(delay);
            queue.add(delayEvent);
        }
    }
}
public class DelayDequeMain {
    public static void main(String[] args) throws Exception {
        DelayQueue<DelayEvent> queue = new DelayQueue<DelayEvent>();
        Thread threads[] = new Thread[5];
        for (int i = 0; i < threads.length; i++) {
            DelayTask task = new DelayTask(i + 1, queue);
            threads[i] = new Thread(task);
        }
        for (int i = 0; i < threads.length; i++) {
            threads[i].start();
        }
        for (int i = 0; i < threads.length; i++) {
            try {
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        do {
            int counter = 0;
            DelayEvent delayEvent;
            do {
                delayEvent = queue.poll();
                if (delayEvent != null) {
                    counter++;
                }
            } while (delayEvent != null);
            System.out.println("At " + new Date() + " you have read " + counter+ " event");
            TimeUnit.MILLISECONDS.sleep(500);
        } while (queue.size() > 0);
    }
}
Thread 3 Fri May 06 11:00:20 CST 2016
Thread 1 Fri May 06 11:00:18 CST 2016
Thread 5 Fri May 06 11:00:22 CST 2016
Thread 4 Fri May 06 11:00:21 CST 2016
Thread 2 Fri May 06 11:00:19 CST 2016
At Fri May 06 11:00:17 CST 2016 you have read 0 event
At Fri May 06 11:00:18 CST 2016 you have read 0 event
At Fri May 06 11:00:18 CST 2016 you have read 100 event
At Fri May 06 11:00:19 CST 2016 you have read 0 event
At Fri May 06 11:00:19 CST 2016 you have read 100 event
At Fri May 06 11:00:20 CST 2016 you have read 0 event
At Fri May 06 11:00:20 CST 2016 you have read 100 event
At Fri May 06 11:00:21 CST 2016 you have read 0 event
At Fri May 06 11:00:21 CST 2016 you have read 100 event
At Fri May 06 11:00:22 CST 2016 you have read 0 event
At Fri May 06 11:00:22 CST 2016 you have read 100 event
相關文章
相關標籤/搜索