Java-多線程-條件隊列

一糟秘、隊列Queue類型

JUC包中隊列Queue是用于存儲線程任務(wù),常見的Queue類型有ArrayBlockingQueue球散、LinkedBlockingQueue尿赚、PriorityBlockingQueue和DelayQueue。

ArrayBlockingQueue

由數(shù)組組成的有界隊列蕉堰,隊列基于數(shù)組實現(xiàn),容量大小在創(chuàng)建ArrayBlockingQueue對象時已定義好吼畏,不可擴容嘁灯。

LinkedBlockingQueue

由鏈接節(jié)點組成的可選有界隊列泻蚊,隊列基于數(shù)組實現(xiàn),容量大小在創(chuàng)建LinkedBlockingQueue對象時已定義好,不可擴容丑婿。

PriorityBlockingQueue

由優(yōu)先級堆組成的無界優(yōu)先級隊列性雄,內(nèi)部線程是阻塞的,使用必須實現(xiàn)compareTo方法羹奉,這里的無界是理論上的秒旋。

DelayQueue

由優(yōu)先級堆支持的、基于時間的調(diào)度隊列诀拭,由優(yōu)先級堆支持的迁筛、基于時間的調(diào)度隊列,內(nèi)部基于無界隊列PriorityQueue實現(xiàn)耕挨,而無界隊列基于數(shù)組的擴容實現(xiàn)细卧。入隊的對象必須要實現(xiàn)Delayed接口。

public static void main(String[] args) {
    DelayQueue<MovieTiket> delayQueue = new DelayQueue<MovieTiket>();
    MovieTiket tiket = new MovieTiket("電影票0",10000);
    delayQueue.put(tiket);
    MovieTiket tiket1 = new MovieTiket("電影票1",5000);
    delayQueue.put(tiket1);
    MovieTiket tiket2 = new MovieTiket("電影票2",8000);
    delayQueue.put(tiket2);
    System.out.println("message:--->入隊完畢");

    while( delayQueue.size() > 0 ){
        try {
            tiket = delayQueue.take();
            System.out.println("電影票出隊:"+tiket.getMsg());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class MovieTiket implements Delayed {
    //延遲時間
    private final long delay;
    //到期時間
    private final long expire;
    //數(shù)據(jù)
    private final String msg;
    //創(chuàng)建時間
    private final long now;

    public MovieTiket(String msg , long delay) {
        this.delay = delay;
        this.msg = msg;
        expire = System.currentTimeMillis() + delay;    //到期時間 = 當前時間+延遲時間
        now = System.currentTimeMillis();
    }

    /**
     * 用于延遲隊列內(nèi)部比較排序  當前時間的延遲時間 - 比較對象的延遲時間
     * 越早過期的時間在隊列中越靠前
     * @param delayed
     * @return
     */
    public int compareTo(Delayed delayed) {
        return (int) (this.getDelay(TimeUnit.MILLISECONDS)
            - delayed.getDelay(TimeUnit.MILLISECONDS));
    }
}

二筒占、Condition隊列

BlockingQueue底層都是基于ReentrantLock 與 Condition隊列實現(xiàn)的贪庙,這也是Condition隊列只能在獨占模式下使用的原因。
多線程下的BlockingQueue是怎樣操作的翰苫?

image.png

若BlockingQueue初始容量為1止邮,T1 T2 同時操作BlockingQueue这橙,T1不斷往BlockingQueue放,T2不斷從BlockingQueue 取导披。T1 在放完第一次后屈扎,BlockingQueue已滿,無法繼續(xù)放了撩匕,T1阻塞助隧,T2喚醒,直到BlockingQueue容量為0滑沧;T2從BlockingQueue取出并村,取完第一次后,BlockingQueue為空滓技,無法繼續(xù)取了哩牍,T2阻塞,T1喚醒令漂,直到BlockingQueue容量為1膝昆。
條件關(guān)鍵:BlockingQueue的容量。

image.png

BlockingQueue的創(chuàng)建會創(chuàng)建一個ReentrantLock叠必、兩個隊列(NotFull與NotEmpty)荚孵。

public ArrayBlockingQueue(int capacity, boolean fair) {
    if (capacity <= 0)
        throw new IllegalArgumentException();
    this.items = new Object[capacity];
    lock = new ReentrantLock(fair);
    notEmpty = lock.newCondition();
    notFull =  lock.newCondition();
}

ReentrantLock中用于多線程的同步操作,NotFull與NotEmpty用于存儲不同條件的線程任務(wù)纬朝。ArrayBlockingQueue的put 和 take操作都需要配合ReentrantLock的使用收叶,只有線程獲取到鎖的線程才能執(zhí)行put 和 take操作。
注意1:BlockingQueue put操作是通過獲取ReentrantLock鎖共苛,進入條件隊列而不是CLH同步隊列判没,同時線程會調(diào)用await方法進入阻塞狀態(tài)。
注意2:條件隊列中阻塞線程不會被喚醒隅茎,只有把條件隊列中的線程移到CLH同步隊列中才會被喚醒澄峰。

image.png

三、HashMap線程不安全

死鎖

Java 1.7 HashMap會產(chǎn)生死鎖辟犀,其數(shù)據(jù)結(jié)構(gòu)為數(shù)組+鏈表俏竞。在多線程場景下,擴容期間存在節(jié)點位置互換指針引用的問題有可能導致閉環(huán)堂竟,主要原因還是鏈表中節(jié)點在擴容的時候位置發(fā)生了變化魂毁。
Java 1.8 HashMap后不會產(chǎn)生死鎖,其數(shù)據(jù)結(jié)構(gòu)為數(shù)組+紅黑樹跃捣。

數(shù)據(jù)丟失

HashMap的put操作在多線程下有可能產(chǎn)生相同的hashcode漱牵,從而造成數(shù)據(jù)覆蓋夺蛇,進而造成數(shù)據(jù)丟失疚漆。Java 1.7 1.8 HashMap都會產(chǎn)生這樣的問題。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市娶聘,隨后出現(xiàn)的幾起案子闻镶,更是在濱河造成了極大的恐慌,老刑警劉巖丸升,帶你破解...
    沈念sama閱讀 212,222評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件铆农,死亡現(xiàn)場離奇詭異,居然都是意外死亡狡耻,警方通過查閱死者的電腦和手機墩剖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,455評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來夷狰,“玉大人岭皂,你說我怎么就攤上這事≌油罚” “怎么了爷绘?”我有些...
    開封第一講書人閱讀 157,720評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長进倍。 經(jīng)常有香客問我土至,道長,這世上最難降的妖魔是什么猾昆? 我笑而不...
    開封第一講書人閱讀 56,568評論 1 284
  • 正文 為了忘掉前任陶因,我火速辦了婚禮,結(jié)果婚禮上垂蜗,老公的妹妹穿的比我還像新娘坑赡。我一直安慰自己,他們只是感情好么抗,可當我...
    茶點故事閱讀 65,696評論 6 386
  • 文/花漫 我一把揭開白布毅否。 她就那樣靜靜地躺著,像睡著了一般蝇刀。 火紅的嫁衣襯著肌膚如雪螟加。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,879評論 1 290
  • 那天吞琐,我揣著相機與錄音捆探,去河邊找鬼。 笑死站粟,一個胖子當著我的面吹牛黍图,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播奴烙,決...
    沈念sama閱讀 39,028評論 3 409
  • 文/蒼蘭香墨 我猛地睜開眼助被,長吁一口氣:“原來是場噩夢啊……” “哼剖张!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起揩环,我...
    開封第一講書人閱讀 37,773評論 0 268
  • 序言:老撾萬榮一對情侶失蹤搔弄,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后丰滑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體顾犹,經(jīng)...
    沈念sama閱讀 44,220評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,550評論 2 327
  • 正文 我和宋清朗相戀三年褒墨,在試婚紗的時候發(fā)現(xiàn)自己被綠了炫刷。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,697評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡郁妈,死狀恐怖柬唯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情圃庭,我是刑警寧澤锄奢,帶...
    沈念sama閱讀 34,360評論 4 332
  • 正文 年R本政府宣布,位于F島的核電站剧腻,受9級特大地震影響拘央,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜书在,卻給世界環(huán)境...
    茶點故事閱讀 40,002評論 3 315
  • 文/蒙蒙 一灰伟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧儒旬,春花似錦栏账、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,782評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至甚垦,卻和暖如春茶鹃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背艰亮。 一陣腳步聲響...
    開封第一講書人閱讀 32,010評論 1 266
  • 我被黑心中介騙來泰國打工闭翩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人迄埃。 一個月前我還...
    沈念sama閱讀 46,433評論 2 360
  • 正文 我出身青樓疗韵,卻偏偏與公主長得像,于是被迫代替她去往敵國和親侄非。 傳聞我的和親對象是個殘疾皇子蕉汪,可洞房花燭夜當晚...
    茶點故事閱讀 43,587評論 2 350

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