之前不管讀任何書蒿囤,都告訴你wait方法阻塞,notify是隨機喚醒一個崇决,notifyAll方法是一次喚醒所有材诽。我想大部分人在實際面試時候也是這樣回答的底挫,但是我今天做了個小小的測試,發(fā)現(xiàn)事實并非如此脸侥,此疑問來自http://www.reibang.com/p/f4454164c017文章建邓。
該文中提到,notify實際是喚醒的第一個進入阻塞列表的線程睁枕,我也比較疑惑官边,于是寫了個小demo測試。
思路如下外遇,先依次創(chuàng)建100個線程進入wait隊列注簿,然后在創(chuàng)建一百個線程去依次喚醒,然后再此時一次喚醒所有跳仿。不多說直接貼代碼:
先來第一個 ?100次wait诡渴,100次notify,在阻塞時候讓線程休眠100秒是為了保證順序進入阻塞隊列塔嬉,
下面是結(jié)果玩徊,
看到?jīng)]有,都是成對出現(xiàn)的谨究,也就是喚醒的線程總是喚醒按順序入隊時候的線程。你們可以自己測試泣棋,我測試了很多次一直都是一個結(jié)果胶哲。這里如果把喚醒的for循環(huán)去掉,只喚醒一個潭辈,我試了很多次一直都是喚醒的是線程0鸯屿,也就是第一個進入阻塞隊列的。如果是隨機喚醒把敢,那么背喚醒的線程就不應該是順序入隊的情況呀寄摆。
我們下面測試notifyAll()
代碼稍稍更改下
下面是輸出結(jié)果
結(jié)果卻是倒敘的。我測試了多次修赞,依然是倒敘婶恼,然后同樣把阻塞后面的沉睡100毫秒睡眠去掉后多次測試
發(fā)現(xiàn)依然是倒敘輸出,測試多次柏副,沒有改變勾邦。難道書上都是錯的嗎?
我們繼續(xù)把創(chuàng)建線程時候的睡眠時間去掉割择,在阻塞前輸出當前入隊阻塞的線程號眷篇,然后依次喚醒所有看輸出順序和入隊順序是否逆一致?
被喚醒的線程順序是:
我們發(fā)現(xiàn)驚奇的一致荔泳,notify是按照入隊阻塞的逆序一致性進行喚醒操作的蕉饼。
到這里大家明白了沒虐杯?
我僅僅是工作不到一年的小白,如果我的測試有錯誤昧港,還請指正厦幅。