Java中join()方法的理解

thread.Join把指定的線程加入到當前線程,能夠將兩個交替執行的線程合併爲順序執行的線程。java

好比在線程B中調用了線程A的Join()方法,直到線程A執行完畢後,纔會繼續執行線程B。ide

t.join();      //調用join方法,等待線程t執行完畢
t.join(1000);  //等待 t 線程,等待時間是1000毫秒。
this

下面是一段JDK中的代碼:spa

    /**
     *  Waits at most <code>millis</code> milliseconds for this thread to  
     * die. A timeout of <code>0</code> means to wait forever.    
     */
    
    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;
            }
        }
    }

從代碼上看,若是線程被生成了,但還未被起動,調用它的 join() 方法是沒有做用的,將直接繼續向下執行線程

Join方法實現是經過wait(小提示:Object 提供的方法)。 當main線程調用t.join時候,main線程會得到線程對象t的鎖(wait 意味着拿到該對象的鎖),調用該對象的wait(等待時間),直到該對象喚醒main線程 ,好比退出後。這就意味着main 線程調用t.join時,必須可以拿到線程t對象的鎖code

經過下面一段代碼解釋:對象

package ThreadTest;

import static java.lang.Thread.currentThread;
import static java.lang.Thread.sleep;

/**
 * Created with IntelliJ IDEA.
 * User: Blank
 * Date: 14-3-28
 * Time: 下午7:49
 */
public class TestJoin implements Runnable {


    public static void main(String[] sure) throws InterruptedException {
        Thread t = new Thread(new TestJoin());
        long start = System.currentTimeMillis();
        t.start();
        t.join(1000);//等待線程t 1000毫秒
        System.out.println(System.currentTimeMillis()-start);//打印出時間間隔
        System.out.println("Main finished");//打印主線程結束
    }

    @Override
    public void run() {
       // synchronized (currentThread()) {
            for (int i = 1; i <= 5; i++) {
                try {
                    sleep(1000);//睡眠5秒,循環是爲了方便輸出信息
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("睡眠" + i);
            }
            System.out.println("TestJoin finished");//t線程結束
        }
    //}
}

在註釋掉synchronized修飾的run方法後,打印信息以下:blog

 

能夠看到main線程等待了t線程1000毫秒以後,結束了,隨後是t線程打印的數據。it

那麼若是加上run方法的synchronized那條語句呢?結果以下:io

因爲先調用了t.start()方法,線程進入synchronized代碼段,main線程等待一秒之後,仍是得不到線程t的對象鎖,只能繼續等待,直到線程t結束,釋放鎖。這裏能夠明確看到main線程等待時間是5000ms,有些文章裏寫的是t線程執行時間+join方法指定的時間(5000+1000 ),其實不是的,這裏能夠很清晰的看到,main線程等待時間只有5000ms,看到有的文章說join調用的wait也是須要獲取對象鎖的。

JDK源代碼中wait操做是

public final native void wait(long timeout) throws InterruptedException;

wait內部實現應該是用synchronized,等待時間是5000+1000就好解釋了,搞不明白。

此處存疑。

相關文章
相關標籤/搜索