Java多線程中,wait()和join()的區(qū)別,帶你入門不放棄

前述

面試過的小伙伴,應(yīng)該都被問到過這個問題。估計被問蒙蒙的不少 :-D
今天我們可以一起來分析一下,文章不長,相信你通過這一篇文章,就可以有很好的掌握了!

一、方法的歸屬

  • wait()方法是object類的方法
  • join()是Thread的方法。

二、 不正經(jīng)的解釋

  • wait()我要休息一會,我累了


  • join()老子要插隊,都NM給我讓開,都等一等


    image

官方一點(diǎn)的說法:

Wait的用法:
當(dāng)一個線程調(diào)用wait的時候,會釋放同步鎖,然后該線程進(jìn)入等待狀態(tài)。其他掛起的線程會競爭這個鎖,得到鎖的繼續(xù)執(zhí)行。

join的用法:
一個線程運(yùn)行中調(diào)用另外線程的JOIN方法,則當(dāng)前線程停止執(zhí)行,一直等到新join進(jìn)來的線程執(zhí)行完畢,才會繼續(xù)執(zhí)行??!

join的測試用例:

一、不加join

public class Main{
public static void main(String[] args) {
        System.out.println("Main 線程 開始運(yùn)行!");
         Thread t1 = new Thread(){
             @Override
             public void run(){
                 System.out.println("t1 開始運(yùn)行!");
                 System.out.println("t1 結(jié)束運(yùn)行!");
             }
         };
         t1.start();
         System.out.println("Main 線程 結(jié)束運(yùn)行!");
    }
}

打印結(jié)果為:
Main 線程 開始運(yùn)行!
Main 線程 結(jié)束運(yùn)行!
t1 開始運(yùn)行!
t1 結(jié)束運(yùn)行!

說明主線程執(zhí)行完畢,才執(zhí)行的子線程t1,這個大家都懂!

二、加join

public class Main{
    public static void main(String[] args) {
        System.out.println("Main 線程 開始運(yùn)行!");
         Thread t1 = new Thread(){
             @Override
             public void run(){
                 System.out.println("t1 開始運(yùn)行!");
                 System.out.println("t1 結(jié)束運(yùn)行!");
             }
         };
         try{
             t1.start();
             t1.join();
         }catch(Exception e){
             
         }
         System.out.println("Main 線程 結(jié)束運(yùn)行!");
    }
}

打印結(jié)果為:
Main 線程 開始運(yùn)行!
t1 開始運(yùn)行!
t1 結(jié)束運(yùn)行!
Main 線程 結(jié)束運(yùn)行!

說明t1線程插隊了,直到t1運(yùn)行完畢,主線程才繼續(xù)運(yùn)行。
所以我們可以先簡單理解為join就是新線程插隊執(zhí)行(當(dāng)前運(yùn)行線程阻塞直到新線程運(yùn)行結(jié)束?。?/p>

接下里我們拋出問題,然后再來認(rèn)真分析join()的原理。

問題1:

上面例子中,我們把join()和start()調(diào)換個順序,會發(fā)現(xiàn)輸出結(jié)果為:

Main 線程 開始運(yùn)行!
Main 線程 結(jié)束運(yùn)行!
t1 開始運(yùn)行!
t1 結(jié)束運(yùn)行!

why??
下面我們來分析源碼Thread.java

public final void join(long millis) throws InterruptedException {
        synchronized(lock) {//主線程拿到lock鎖
        long base = System.currentTimeMillis();

        if (millis == 0) {
            while (isAlive()) { //由于該線程已經(jīng)start(),所以視為alive
                lock.wait(0);  
                //主線程釋放鎖,進(jìn)入無限期的等待狀態(tài)。
               //直到子線程完成run,釋放鎖,然后主線程會重新拿到鎖頭繼續(xù)運(yùn)行
               //拿到鎖之后,isAlive()不成立了,所以退出while循環(huán)??!
            }
        } else {
            }
        }
        }
    }

調(diào)用join()時, 默認(rèn)millis為0。
如上代碼,如果沒有先執(zhí)行start()直接執(zhí)行join,則isAlive()返回為false,則主線程不會堵塞進(jìn)入wait(0),這就是為什么一定要先start()然后再join()的原因所在。

問題2:

為什么join()可以阻塞主線程,直到子線程執(zhí)行完畢??
同樣看上面代碼:

  • 主線程進(jìn)入join()方法
  • 主線程拿到子線程的lock鎖
  • 進(jìn)入同步代碼快
  • while (isAlive()) 成立,因為先調(diào)用了start()方法
  • 調(diào)用 lock.wait(0), 主線程釋放鎖,進(jìn)入wait狀態(tài)
  • 子線程開始執(zhí)行,執(zhí)行結(jié)束會調(diào)用lock.notifyAll(),通知主線程獲得鎖。
  • 主線程重新啟動, while (isAlive()) 已經(jīng)不成立(由于子線程不再是alive狀態(tài))
  • 主線程繼續(xù)往下運(yùn)行。

其中倒數(shù)第三部,是在jdk的Thread.cpp里完成的,可以先不做研究!!

image.jpeg

相信到此,你大致了解了一下機(jī)理。

總結(jié)與綜述

  • wait是object類的方法
  • join是Thread類的方法
  • Wait的用法:當(dāng)一個線程調(diào)用wait的時候,會釋放同步鎖,然后該線程進(jìn)入等待狀態(tài)。其他掛起的線程會競爭這個鎖,得到鎖的繼續(xù)執(zhí)行。
  • join的用法:一個線程A運(yùn)行中調(diào)用線程B.join()方法,則A線程停止執(zhí)行,一直等到B線程執(zhí)行完畢,A線程才會繼續(xù)執(zhí)行!!
  • join方法的實現(xiàn),利用了wait()和notifyAll()方法。

搞定~~~ 有問題歡迎一起交流

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文主要講了java中多線程的使用方法、線程同步、線程數(shù)據(jù)傳遞、線程狀態(tài)及相應(yīng)的一些線程函數(shù)用法、概述等。 首先講...
    李欣陽閱讀 2,599評論 1 15
  • Java多線程學(xué)習(xí) [-] 一擴(kuò)展javalangThread類 二實現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 3,111評論 1 18
  • 一擴(kuò)展javalangThread類二實現(xiàn)javalangRunnable接口三Thread和Runnable的區(qū)...
    和帥_db6a閱讀 594評論 0 1
  • 林炳文Evankaka原創(chuàng)作品。轉(zhuǎn)載自http://blog.csdn.net/evankaka 本文主要講了ja...
    ccq_inori閱讀 735評論 0 4
  • 一、金句: 1、如何利用規(guī)律和趨勢,放大個人努力。2、你根本不需要掌握這本書里說的所有方法。你真正要做的是一邊實踐...
    艾白羊閱讀 324評論 0 0

友情鏈接更多精彩內(nèi)容