ALL is Well!

          敏捷是一條很長(zhǎng)的路,摸索著前進(jìn)著

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            30 隨筆 :: 23 文章 :: 71 評(píng)論 :: 0 Trackbacks

          一、在研究join的用法之前,先明確兩件事情。

          1.join方法定義在Thread類(lèi)中,則調(diào)用者必須是一個(gè)線程,

          例如:

          Thread t = new CustomThread();//這里一般是自定義的線程類(lèi)

          t.start();//線程起動(dòng)

          t.join();//此處會(huì)拋出InterruptedException異常

           

          2.上面的兩行代碼也是在一個(gè)線程里面執(zhí)行的。

           

          以上出現(xiàn)了兩個(gè)線程,一個(gè)是我們自定義的線程類(lèi),我們實(shí)現(xiàn)了run方法,做一些我們需要的工作;另外一個(gè)線程,生成我們自定義線程類(lèi)的對(duì)象,然后執(zhí)行

          customThread.start();

          customThread.join();

          在這種情況下,兩個(gè)線程的關(guān)系是一個(gè)線程由另外一個(gè)線程生成并起動(dòng),所以我們暫且認(rèn)為第一個(gè)線程叫做“子線程”,另外一個(gè)線程叫做“主線程”。

           

          二、為什么要用join()方法

          主線程生成并起動(dòng)了子線程,而子線程里要進(jìn)行大量的耗時(shí)的運(yùn)算(這里可以借鑒下線程的作用),當(dāng)主線程處理完其他的事務(wù)后,需要用到子線程的處理結(jié)果,這個(gè)時(shí)候就要用到j(luò)oin();方法了。

           

           

          三、join方法的作用

          在網(wǎng)上看到有人說(shuō)“將兩個(gè)線程合并”。這樣解釋我覺(jué)得理解起來(lái)還更麻煩。不如就借鑒下API里的說(shuō)法:

          “等待該線程終止。”

          解釋一下,是主線程(我在“一”里已經(jīng)命名過(guò)了)等待子線程的終止。也就是在子線程調(diào)用了join()方法后面的代碼,只有等到子線程結(jié)束了才能執(zhí)行。(Waits for this thread to die.)

           

           

          四、用實(shí)例來(lái)理解

          寫(xiě)一個(gè)簡(jiǎn)單的例子來(lái)看一下join()的用法,一共三個(gè)類(lèi):

          1.CustomThread 類(lèi)

          2. CustomThread1類(lèi)

          3. JoinTestDemo 類(lèi),main方法所在的類(lèi)。

           

          代碼1:

           1package wxhx.csdn2;   
           2/**  
           3 *   
           4 * @author bzwm  
           5 *  
           6 */
            
           7class CustomThread1 extends Thread {   
           8    public CustomThread1() {   
           9        super("[CustomThread1] Thread");   
          10    }
          ;   
          11    public void run() {   
          12        String threadName = Thread.currentThread().getName();   
          13        System.out.println(threadName + " start.");   
          14        try {   
          15            for (int i = 0; i < 5; i++{   
          16                System.out.println(threadName + " loop at " + i);   
          17                Thread.sleep(1000);   
          18            }
             
          19            System.out.println(threadName + " end.");   
          20        }
           catch (Exception e) {   
          21            System.out.println("Exception from " + threadName + ".run");   
          22        }
             
          23    }
             
          24}
             
          25class CustomThread extends Thread {   
          26    CustomThread1 t1;   
          27    public CustomThread(CustomThread1 t1) {   
          28        super("[CustomThread] Thread");   
          29        this.t1 = t1;   
          30    }
             
          31    public void run() {   
          32        String threadName = Thread.currentThread().getName();   
          33        System.out.println(threadName + " start.");   
          34        try {   
          35            t1.join();   
          36            System.out.println(threadName + " end.");   
          37        }
           catch (Exception e) {   
          38            System.out.println("Exception from " + threadName + ".run");   
          39        }
             
          40    }
             
          41}
             
          42public class JoinTestDemo {   
          43    public static void main(String[] args) {   
          44        String threadName = Thread.currentThread().getName();   
          45        System.out.println(threadName + " start.");   
          46        CustomThread1 t1 = new CustomThread1();   
          47        CustomThread t = new CustomThread(t1);   
          48        try {   
          49            t1.start();   
          50            Thread.sleep(2000);   
          51            t.start();   
          52            t.join();//在代碼2里,將此處注釋掉   
          53        }
           catch (Exception e) {   
          54            System.out.println("Exception from main");   
          55        }
             
          56        System.out.println(threadName + " end!");   
          57    }
             
          58}


          打印結(jié)果:

           

          main start.//main方法所在的線程起動(dòng),但沒(méi)有馬上結(jié)束,因?yàn)檎{(diào)用t.join();,所以要等到t結(jié)束了,此線程才能向下執(zhí)行。

          [CustomThread1] Thread start.//線程CustomThread1起動(dòng)

          [CustomThread1] Thread loop at 0//線程CustomThread1執(zhí)行

          [CustomThread1] Thread loop at 1//線程CustomThread1執(zhí)行

          [CustomThread] Thread start.//線程CustomThread起動(dòng),但沒(méi)有馬上結(jié)束,因?yàn)檎{(diào)用t1.join();,所以要等到t1結(jié)束了,此線程才能向下執(zhí)行。

          [CustomThread1] Thread loop at 2//線程CustomThread1繼續(xù)執(zhí)行

          [CustomThread1] Thread loop at 3//線程CustomThread1繼續(xù)執(zhí)行

          [CustomThread1] Thread loop at 4//線程CustomThread1繼續(xù)執(zhí)行

          [CustomThread1] Thread end. //線程CustomThread1結(jié)束了

          [CustomThread] Thread end.// 線程CustomThread在t1.join();阻塞處起動(dòng),向下繼續(xù)執(zhí)行的結(jié)果

          main end!//線程CustomThread結(jié)束,此線程在t.join();阻塞處起動(dòng),向下繼續(xù)執(zhí)行的結(jié)果。

           

          修改一下代碼,得到代碼2:(這里只寫(xiě)出修改的部分)

           

           1public class JoinTestDemo {   
           2    public static void main(String[] args) {   
           3        String threadName = Thread.currentThread().getName();   
           4        System.out.println(threadName + " start.");   
           5        CustomThread1 t1 = new CustomThread1();   
           6        CustomThread t = new CustomThread(t1);   
           7        try {   
           8            t1.start();   
           9            Thread.sleep(2000);   
          10            t.start();   
          11//          t.join();//在代碼2里,將此處注釋掉   
          12        }
           catch (Exception e) {   
          13            System.out.println("Exception from main");   
          14        }
             
          15        System.out.println(threadName + " end!");   
          16    }
             
          17}


          打印結(jié)果:

           

          main start. // main方法所在的線程起動(dòng),但沒(méi)有馬上結(jié)束,這里并不是因?yàn)閖oin方法,而是因?yàn)門(mén)hread.sleep(2000);

          [CustomThread1] Thread start. //線程CustomThread1起動(dòng)

          [CustomThread1] Thread loop at 0//線程CustomThread1執(zhí)行

          [CustomThread1] Thread loop at 1//線程CustomThread1執(zhí)行

          main end!// Thread.sleep(2000);結(jié)束,雖然在線程CustomThread執(zhí)行了t1.join();,但這并不會(huì)影響到其他線程(這里main方法所在的線程)。

          [CustomThread] Thread start. //線程CustomThread起動(dòng),但沒(méi)有馬上結(jié)束,因?yàn)檎{(diào)用t1.join();,所以要等到t1結(jié)束了,此線程才能向下執(zhí)行。

          [CustomThread1] Thread loop at 2//線程CustomThread1繼續(xù)執(zhí)行

          [CustomThread1] Thread loop at 3//線程CustomThread1繼續(xù)執(zhí)行

          [CustomThread1] Thread loop at 4//線程CustomThread1繼續(xù)執(zhí)行

          [CustomThread1] Thread end. //線程CustomThread1結(jié)束了

          [CustomThread] Thread end. // 線程CustomThread在t1.join();阻塞處起動(dòng),向下繼續(xù)執(zhí)行的結(jié)果

           

           

          五、從源碼看join()方法

           

          在CustomThread的run方法里,執(zhí)行了t1.join();,進(jìn)入看一下它的JDK源碼:

           

          1public final void join() throws InterruptedException {   
          2join(0);   
          3}
            

          然后進(jìn)入join(0)方法:

           1   /**  
           2    * Waits at most <code>millis</code> milliseconds for this thread to   
           3    * die. A timeout of <code>0</code> means to wait forever. //注意這句  
           4    *  
           5    * @param      millis   the time to wait in milliseconds.  
           6    * @exception  InterruptedException if another thread has interrupted  
           7    *             the current thread.  The <i>interrupted status</i> of the  
           8    *             current thread is cleared when this exception is thrown.  
           9    */
            
          10   public final synchronized void join(long millis) //參數(shù)millis為0.   
          11   throws InterruptedException {   
          12long base = System.currentTimeMillis();   
          13long now = 0;   
          14if (millis < 0{   
          15           throw new IllegalArgumentException("timeout value is negative");   
          16}
             
          17if (millis == 0{//進(jìn)入這個(gè)分支   
          18    while (isAlive()) {//判斷本線程是否為活動(dòng)的。這里的本線程就是t1.   
          19    wait(0);//阻塞   
          20    }
             
          21}
           else {   
          22    while (isAlive()) {   
          23    long delay = millis - now;   
          24    if (delay <= 0{   
          25        break;   
          26    }
             
          27    wait(delay);   
          28    now = System.currentTimeMillis() - base;   
          29    }
             
          30}
             
          31   }
           

           

          單純從代碼上看,如果線程被生成了,但還未被起動(dòng),調(diào)用它的join()方法是沒(méi)有作用的。將直接繼續(xù)向下執(zhí)行,這里就不寫(xiě)代碼驗(yàn)證了。

          ----2009年02月12日

          posted on 2010-09-01 11:52 李 明 閱讀(56030) 評(píng)論(16)  編輯  收藏 所屬分類(lèi): J2SE 、技術(shù)知識(shí)

          評(píng)論

          # re: 淺析 Java Thread.join()[未登錄](méi) 2011-10-10 10:11 test
          二、為什么要用join()方法

          主線程生成并起動(dòng)了子線程,而子線程里要進(jìn)行大量的耗時(shí)的運(yùn)算(這里可以借鑒下線程的作用),當(dāng)主線程處理完其他的事務(wù)后,需要用到子線程的處理結(jié)果,這個(gè)時(shí)候就要用到j(luò)oin();方法了。

          ????????????????????
          感覺(jué)這段很成問(wèn)題  回復(fù)  更多評(píng)論
            

          # re: 淺析 Java Thread.join() 2011-10-29 13:25 zhangyou1010
          t.start();//線程起動(dòng)

          t.join();//此處會(huì)拋出InterruptedException異常

          上面這段代碼,不會(huì)異常啊。  回復(fù)  更多評(píng)論
            

          # re: 淺析 Java Thread.join()[未登錄](méi) 2013-03-21 11:37 minelibra
          就像主線程是開(kāi)會(huì)一樣,會(huì)議(主線程)正在進(jìn)行中,這時(shí)候需要一個(gè)人join進(jìn)來(lái)(子線程啟動(dòng)),并執(zhí)行他自己的操作,如果他的操作沒(méi)有執(zhí)行完畢,則會(huì)議(主線程)不能結(jié)束。  回復(fù)  更多評(píng)論
            

          # re: 淺析 Java Thread.join() 2013-05-11 00:05 億可達(dá)西靚
          @test
          比如:你準(zhǔn)備洗澡,需要準(zhǔn)備的步驟,準(zhǔn)備好衣服,沐浴的東西及燒水這些事情,由于燒水耗時(shí)太長(zhǎng),如果也放在主線程之中,就很浪費(fèi)資源,所以如果我們另開(kāi)線程去處理,就會(huì)達(dá)到很好效果,于是乎在準(zhǔn)備好衣服,沐浴的東西之前就去開(kāi)子線程燒水,燒水的過(guò)程中主線程準(zhǔn)備好衣服,沐浴的東西,此時(shí)就等待水燒好,然后方可痛快的洗澡了!!  回復(fù)  更多評(píng)論
            

          # re: 淺析 Java Thread.join() 2013-07-25 14:44 emmet7life
          @minelibra
          這個(gè)解釋不錯(cuò)喲  回復(fù)  更多評(píng)論
            

          # re: 淺析 Java Thread.join()[未登錄](méi) 2013-09-12 07:08 Mark
          這個(gè)簡(jiǎn)單的東西,你搞那么復(fù)雜。主線程等待調(diào)用join方法的子線程執(zhí)行結(jié)束后再繼續(xù)執(zhí)行  回復(fù)  更多評(píng)論
            

          # re: 淺析 Java Thread.join()[未登錄](méi) 2013-12-12 10:15 Jack
          @Mark
          說(shuō)的對(duì)  回復(fù)  更多評(píng)論
            

          # re: 淺析 Java Thread.join() 2014-06-12 16:41 11
          什么問(wèn)題?@test
            回復(fù)  更多評(píng)論
            

          # re: 淺析 Java Thread.join()[未登錄](méi) 2014-06-17 14:25 YY
          你和朋友一起吃飯,突然你肚子痛,要拉屎,這個(gè)時(shí)候你去了廁所拉屎,拉了很久,但是你的朋友們要等你拉完回來(lái)在一起AA  回復(fù)  更多評(píng)論
            

          # re: 淺析 Java Thread.join() 2014-06-17 14:30 @YY
          精辟  回復(fù)  更多評(píng)論
            

          # re: 淺析 Java Thread.join() 2014-06-17 14:35 頭很大
          @YY
          這..... 這個(gè)知識(shí)點(diǎn) 我懂了  回復(fù)  更多評(píng)論
            

          # re: 淺析 Java Thread.join() 2014-08-19 14:31 reiike
          麻煩樓主把文章理一理,這么混亂不清還寫(xiě)篇文章,服了。  回復(fù)  更多評(píng)論
            

          # re: 淺析 Java Thread.join() 2014-08-19 14:36 reiike

          http://www.open-open.com/lib/view/open1371741636171.html

          別人的文章,論文章排版,整潔干凈,論解釋,邏輯清晰,前后連貫。  回復(fù)  更多評(píng)論
            

          # re: 淺析 Java Thread.join() 2014-10-09 09:09 chanedi
          @reiike
          這兩個(gè)文章不是一樣嗎?  回復(fù)  更多評(píng)論
            

          # re: 淺析 Java Thread.join()[未登錄](méi) 2014-12-26 16:47 peter
          @YY
          這個(gè)解釋口味好重  回復(fù)  更多評(píng)論
            


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 四子王旗| 平遥县| 邹平县| 布尔津县| 巫山县| 莱州市| 恩平市| 砀山县| 司法| 克东县| 乐清市| 湖南省| 玛纳斯县| 冀州市| 垣曲县| 二手房| 深泽县| 赞皇县| 彝良县| 诸城市| 北票市| 凤翔县| 高邮市| 大姚县| 寻乌县| 枣阳市| 迁安市| 灵川县| 武邑县| 平阴县| 崇文区| 宁都县| 遵义县| 安庆市| 平江县| 巫山县| 秦安县| 寻甸| 讷河市| 梅河口市| 开封县|