DelayedQueue學(xué)習(xí)筆記

概述

DelayQueuejava.util.concurrent中提供的一個(gè)很有意思的類蚊荣。本文將會(huì)對(duì)DelayQueue做一個(gè)介紹,然后列舉應(yīng)用場(chǎng)景。并且提供一個(gè)Delayed接口的實(shí)現(xiàn)和 Sample 代碼。

DelayQueue是一個(gè)無(wú)界的BlockingQueue江滨,用于放置實(shí)現(xiàn)了Delayed接口的對(duì)象,其中的對(duì)象只能在其到期時(shí)才能從隊(duì)列中取走厌均。這種隊(duì)列是有序的唬滑,即隊(duì)頭對(duì)象的延遲到期時(shí)間最長(zhǎng)。注意:不能將null元素放置到這種隊(duì)列中棺弊。

Delayed晶密,一種混合風(fēng)格的接口,用來(lái)標(biāo)記那些應(yīng)該在給定延遲時(shí)間之后執(zhí)行的對(duì)象模她。Delayed擴(kuò)展了Comparable接口稻艰,比較的基準(zhǔn)為延時(shí)的時(shí)間值,Delayed接口的實(shí)現(xiàn)類getDelay的返回值應(yīng)為固定值(final)侈净。DelayQueue內(nèi)部是使用PriorityQueue實(shí)現(xiàn)的尊勿。

應(yīng)用舉例

DelayQueue阻塞隊(duì)列在我們系統(tǒng)開發(fā)中也常常會(huì)用到,例如:緩存系統(tǒng)的設(shè)計(jì)畜侦,緩存中的對(duì)象元扔,超過(guò)了空閑時(shí)間,需要從緩存中移出旋膳;任務(wù)調(diào)度系統(tǒng)澎语,能夠準(zhǔn)確的把握任務(wù)的執(zhí)行時(shí)間。我們可能需要通過(guò)線程處理很多時(shí)間上要求很嚴(yán)格的數(shù)據(jù),如果使用普通的線程擅羞,我們就需要遍歷所有的對(duì)象尸变,一個(gè)一個(gè)的檢查看數(shù)據(jù)是否過(guò)期等,首先這樣在執(zhí)行上的效率不會(huì)太高减俏,其次就是這種設(shè)計(jì)的風(fēng)格也大大的影響了數(shù)據(jù)的精度召烂。一個(gè)需要12:00點(diǎn)執(zhí)行的任務(wù)可能12:01才執(zhí)行,這樣對(duì)數(shù)據(jù)要求很高的系統(tǒng)有更大的弊端。由此我們可以使用DelayQueue垄懂。

我們?cè)诰W(wǎng)咖或者網(wǎng)吧上網(wǎng)時(shí)會(huì)用到一個(gè)網(wǎng)吧綜合系統(tǒng),其中有一個(gè)主要功能就是給每一位網(wǎng)民計(jì)時(shí)痛垛,用戶充值一定金額會(huì)有相應(yīng)的上網(wǎng)時(shí)常草慧,這里我們用DelayQueue模擬實(shí)現(xiàn)一下:

DelayQueue存儲(chǔ)網(wǎng)民(Wangmin類),每一個(gè)考生都有自己的名字和完成試卷的時(shí)間匙头,Wangba線程對(duì)DelayQueue進(jìn)行監(jiān)控漫谷,從隊(duì)列中取出到時(shí)間的網(wǎng)民執(zhí)行下機(jī)操作。

實(shí)現(xiàn)了Delayed接口的網(wǎng)民類

public class Wangmin implements Delayed {  

    private String name;  
    //身份證  
    private String id;  
    //截止時(shí)間  
    private long endTime;  
    //定義時(shí)間工具類
    private TimeUnit timeUnit = TimeUnit.SECONDS;
      
    public Wangmin(String name,String id,long endTime){  
        this.name=name;  
        this.id=id;  
        this.endTime = endTime;  
    }  
      
    public String getName(){  
        return this.name;  
    }  
      
    public String getId(){  
        return this.id;  
    }  
      
    /** 
     * 用來(lái)判斷是否到了截止時(shí)間 
     */  
    @Override  
    public long getDelay(TimeUnit unit) { 
        //return unit.convert(endTime, TimeUnit.MILLISECONDS) - unit.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS);
        return endTime - System.currentTimeMillis();
    }  
  
    /** 
     * 相互批較排序用 
     */  
    @Override  
    public int compareTo(Delayed delayed) {  
        Wangmin w = (Wangmin)delayed;  
        return this.getDelay(this.timeUnit) - w.getDelay(this.timeUnit) > 0 ? 1:0;  
    }    
}

網(wǎng)吧類

public class WangBa implements Runnable {  

    private DelayQueue<Wangmin> queue = new DelayQueue<Wangmin>();  
    
    public boolean yingye =true;  
    
    /**
     * 上機(jī) 
     */
    public void shangji(String name,String id,int money){  
        Wangmin man = new Wangmin(name, id, 1000 * money + System.currentTimeMillis());  
        System.out.println("網(wǎng)名"+man.getName()+" 身份證"+man.getId()+"交錢"+money+"塊,開始上機(jī)...");  
        this.queue.add(man);  
    }  
    
    // 下機(jī)
    public void xiaji(Wangmin man){  
        System.out.println("網(wǎng)名"+man.getName()+" 身份證"+man.getId()+"時(shí)間到下機(jī)...");  
    }  
  
    @Override  
    public void run() {  
        while(yingye){  
            try {  
                Wangmin man = queue.take();  
                xiaji(man);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
      
    public static void main(String args[]){  
        try{  
            System.out.println("網(wǎng)吧開始營(yíng)業(yè)");  
            WangBa siyu = new WangBa();  
            Thread shangwang = new Thread(siyu);  
            shangwang.start();  
              
            siyu.shangji("路人甲", "123", 1);  
            siyu.shangji("路人乙", "234", 10);  
            siyu.shangji("路人丙", "345", 5);  
        }  
        catch(Exception e){  
            e.printStackTrace();
        }  
  
    }  
}

源碼分析

首先看一下DlayedQueue源碼

public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
implements BlockingQueue<E> {

    private final transient ReentrantLock lock = new ReentrantLock();
    private final PriorityQueue<E> q = new PriorityQueue<E>();

    // ...

}

這是一小部分源碼蹂析,從這段源碼可以看出舔示,DelayedQueue中處理的是實(shí)現(xiàn)Delayed接口的任務(wù),DelayedQueue使用lock來(lái)實(shí)現(xiàn)線程同步电抚,使用PriorityQueue來(lái)管理任務(wù)惕稻。那么Delayed接口是什么呢?

public interface Delayed extends Comparable<Delayed> {

    long getDelay(TimeUnit unit);
}

這是Delayed接口的官方注釋蝙叛,意思是:一個(gè)混合風(fēng)格的接口俺祠,為創(chuàng)建給定延遲的任務(wù)。(翻譯的不太好借帘,請(qǐng)糾正)蜘渣;其中有兩個(gè)重要的方法compareTo和getDelay,第一個(gè)是比較兩個(gè)任務(wù)的延遲時(shí)間進(jìn)行排序肺然,第二個(gè)方法用來(lái)獲取延遲時(shí)間蔫缸。

priorityQueue是一種優(yōu)先級(jí)隊(duì)列,這里優(yōu)先級(jí)就是延遲時(shí)間际起,也就是說(shuō)進(jìn)入隊(duì)列的任務(wù)安裝優(yōu)先級(jí)進(jìn)行排序拾碌,延遲時(shí)間最短的在隊(duì)列前面,先被處理街望,也就是說(shuō)倦沧,每次從隊(duì)列中取出的任務(wù)都將是到期的任務(wù)。比如我們實(shí)現(xiàn)一個(gè)緩存它匕,當(dāng)某個(gè)key-value對(duì)超期了展融,我們就可以從隊(duì)列前取出,然后進(jìn)行銷毀操作。

這里有一個(gè)實(shí)現(xiàn)緩存的例子告希,鏈接如下:
http://www.cnblogs.com/jobs/archive/2007/04/27/730255.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末扑浸,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子燕偶,更是在濱河造成了極大的恐慌喝噪,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件指么,死亡現(xiàn)場(chǎng)離奇詭異酝惧,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)伯诬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門晚唇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人盗似,你說(shuō)我怎么就攤上這事哩陕。” “怎么了赫舒?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵悍及,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我接癌,道長(zhǎng)心赶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任缺猛,我火速辦了婚禮园担,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘枯夜。我一直安慰自己弯汰,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布湖雹。 她就那樣靜靜地躺著咏闪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪摔吏。 梳的紋絲不亂的頭發(fā)上鸽嫂,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音征讲,去河邊找鬼据某。 笑死,一個(gè)胖子當(dāng)著我的面吹牛诗箍,可吹牛的內(nèi)容都是我干的癣籽。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼筷狼!你這毒婦竟也來(lái)了瓶籽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤埂材,失蹤者是張志新(化名)和其女友劉穎塑顺,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體俏险,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡严拒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了竖独。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片裤唠。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖预鬓,靈堂內(nèi)的尸體忽然破棺而出巧骚,到底是詐尸還是另有隱情赊颠,我是刑警寧澤格二,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站竣蹦,受9級(jí)特大地震影響顶猜,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜痘括,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一长窄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧纲菌,春花似錦挠日、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至椅贱,卻和暖如春懂算,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背庇麦。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工计技, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人山橄。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓垮媒,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子涣澡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容