再說Java中wait婆跑、sleep、join和yield方法的區(qū)別

引入

長期以來庭呜,多線程問題頗為受到面試官們的青睞滑进。如果你去參加一個面試,面試官全程沒有問你一個關(guān)于多線程的問題募谎,你都覺得不正規(guī)(哈哈~~)扶关。雖然在我們實(shí)際的開發(fā)過程很少會有開發(fā)復(fù)雜多線程應(yīng)用的機(jī)會,但是通過深入理解它数冬,會讓你在面試與工作中节槐,變得自信與從容搀庶。

關(guān)于java線程基礎(chǔ)

如果對于Java線程基礎(chǔ)不是很了解的同學(xué),可以參考我的另外一篇文章:Java多線程基礎(chǔ)

源碼解讀

wait铜异、sleep哥倔、join和yield這四個方法中史煎, sleep番甩,join和yield定義在Thread類中,
wait定義在Object類中秩冈。下圖展示了一個線程的生命周期:
Thread類:

package java.lang;
public class Thread implements Runnable {
  /**
   * 向調(diào)度程序發(fā)出的提示蚂子,表明當(dāng)前線程愿意放棄使用當(dāng)前的處理器資源沃测。調(diào)度程序可以忽略這個提示。
   *  yield是一種啟發(fā)式的改進(jìn)線程之間的相對進(jìn)程的嘗試食茎,否則會過度使用CPU蒂破。
   *       它的使用應(yīng)該與詳細(xì)的分析和基準(zhǔn)測試相結(jié)合,以確保它實(shí)際具有預(yù)期的效果董瞻。
   * 很少適合使用這種方法寞蚌。對于調(diào)試或測試目的,它可能很有用钠糊,因?yàn)樗梢詭椭噩F(xiàn)由于競態(tài)條件而產(chǎn)生的錯誤
   */
  public static native void yield();
  /**
   * 使當(dāng)前正在執(zhí)行的線程在指定的毫秒數(shù)內(nèi)休眠(臨時停止執(zhí)行)挟秤;
   * 線程在休眠的過程中,不會釋放任何已經(jīng)得到的鎖抄伍;
   */
  public static native void sleep(long millis) throws InterruptedException;

  /**
   * 等待線程死亡的時間最多為{millis}毫秒艘刚,如果{millis}設(shè)置為0時,將意味著一直等待下去截珍。
   * 此實(shí)現(xiàn)使用{this.isAlive()}為條件攀甚,循環(huán)調(diào)用{Object.wait()}方法
   */
  public final synchronized void join(long millis) throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
  }
}

我們可以看到j(luò)oin方法最終是以while循環(huán)的形式,通過檢測當(dāng)前線程isAlive()是否可用岗喉,調(diào)用Object.wait()進(jìn)行阻塞等待秋度。

Object類:

package java.lang;
public class Object {
  public final native void wait(long timeout) throws InterruptedException;
}

所以最終讓線程等待的是Object.wait(), Thread.sleep()和Thread.yield()這三個方法钱床;
而這三個方法都是調(diào)用的C/C++實(shí)現(xiàn)的本地方法荚斯;

Java線程狀態(tài)

一個線程的生命周期中,總共有以下6種狀態(tài)

  • NEW - 這個狀態(tài)主要是線程未被Thread.start()調(diào)用前的狀態(tài)查牌。
  • RUNNABLE - 線程正在JVM中被執(zhí)行事期,它可能正在等待來自操作系統(tǒng)(如處理器)的其他資源。
  • BLOCKED - 線程被阻塞等待一個monitor鎖纸颜,處于阻塞狀態(tài)的線程正在等待monitor鎖進(jìn)入synchronized的代碼塊或方法兽泣,或者在調(diào)用Object.wait()方法后重新進(jìn)入synchronized的代碼塊或方法。
  • WAITING - 由于線程調(diào)用了Object.wait(0)胁孙,Thread.join(0)LockSupport.park其中的一個方法唠倦,線程處于等待狀態(tài)称鳞,其中調(diào)用wait, join方法時未設(shè)置超時時間。還有一種情況牵敷,處于等待狀態(tài)的線程正在等待另一個線程執(zhí)行特定的操作胡岔,比如:一個線程調(diào)用了Object.wait()后,等待另一個線程調(diào)用Object.notifyAll()Object.notify()方法枷餐;或一個線程調(diào)用了Thread.join()方法靶瘸,等待自己的線程的結(jié)束。
  • TIMED_WAITING - 線程等待一個指定的時間毛肋,比如線程調(diào)用了Object.wait(long), Thread.join(long),LockSupport.parkNanos, LockSupport.parkUntil方法之后怨咪,線程的狀態(tài)就會變成TIMED_WAITING
  • TERMINATED - 終止的線程狀態(tài),線程已經(jīng)完成執(zhí)行润匙。

下面我繪制出了一張Java線程的生命周期诗眨,如下圖:


Java線程生命周期

總結(jié)

  1. sleep、yield方法是靜態(tài)方法孕讳;作用的是當(dāng)前執(zhí)行的線程;
  2. yield方法釋放了cpu的執(zhí)行權(quán)匠楚,但是依然保留了cpu的執(zhí)行資格。給個簡單的例子:很多人排隊(duì)上WC厂财,剛好排上yield上了芋簿,現(xiàn)在yield說,出讓它這次機(jī)會璃饱,與更急的人一起比賽誰能更快進(jìn)入到WC中去与斤。這個比賽可能是其他的人,也可能就是yield本身荚恶;
  3. wait釋放CPU資源撩穿,同時釋放鎖;
  4. sleep釋放CPU資源谒撼,但不釋放鎖食寡;
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市廓潜,隨后出現(xiàn)的幾起案子冻河,更是在濱河造成了極大的恐慌,老刑警劉巖茉帅,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異锭弊,居然都是意外死亡堪澎,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進(jìn)店門味滞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來樱蛤,“玉大人钮呀,你說我怎么就攤上這事∽蚍玻” “怎么了爽醋?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長便脊。 經(jīng)常有香客問我蚂四,道長,這世上最難降的妖魔是什么哪痰? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任遂赠,我火速辦了婚禮,結(jié)果婚禮上晌杰,老公的妹妹穿的比我還像新娘跷睦。我一直安慰自己,他們只是感情好肋演,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布抑诸。 她就那樣靜靜地躺著,像睡著了一般爹殊。 火紅的嫁衣襯著肌膚如雪蜕乡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天边灭,我揣著相機(jī)與錄音异希,去河邊找鬼。 笑死绒瘦,一個胖子當(dāng)著我的面吹牛称簿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播惰帽,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼憨降,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了该酗?” 一聲冷哼從身側(cè)響起授药,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎呜魄,沒想到半個月后悔叽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡爵嗅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年娇澎,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片睹晒。...
    茶點(diǎn)故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡趟庄,死狀恐怖括细,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情戚啥,我是刑警寧澤奋单,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站猫十,受9級特大地震影響览濒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜炫彩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一匾七、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧江兢,春花似錦昨忆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至叔磷,卻和暖如春拢驾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背改基。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工繁疤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人秕狰。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓稠腊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鸣哀。 傳聞我的和親對象是個殘疾皇子架忌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評論 2 354

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