代碼詳解のThread.join()實現多個線程順序執行

多線程開發中經常遇到線程間的依賴問題,比如:

       線程T2的運行依賴線程T1的執行結果,線程T3的運行依賴線程T2和線程T4的執行結果,此時 T2和T4是可以並行計算的。

遇到這種問題我們就可以使用Thread.join()方法實現,首先開下join()方法的源碼:

/**
 * Waits at most {@code millis} milliseconds for this thread to
 * die. A timeout of {@code 0} means to wait forever.
 *
 * <p> This implementation uses a loop of {@code this.wait} calls
 * conditioned on {@code this.isAlive}. As a thread terminates the
 * {@code this.notifyAll} method is invoked. It is recommended that
 * applications not use {@code wait}, {@code notify}, or
 * {@code notifyAll} on {@code Thread} instances.
 *
 * @param  millis
 *         the time to wait in milliseconds
 *
 * @throws  IllegalArgumentException
 *          if the value of {@code millis} is negative
 *
 * @throws  InterruptedException
 *          if any thread has interrupted the current thread. The
 *          <i>interrupted status</i> of the current thread is
 *          cleared when this exception is thrown.
 */
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;
        }
    }
}

舉個栗子:

如果在線程t2中我們調用了線程t1的t1.join(默認0ms)方法,意思是:如果線程t1.isAlive(),即線程t1沒有結束,則線程t2 wait(0);即t2一直等待。

代碼實現如下:

public class Thread1Test extends Thread{

    public void run(){
        System.out.println("thread1 開始執行");
        try {
            Thread.sleep(1000);//do something
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("thread1 執行結束");
    }

}
public class Thread2Test extends Thread {
    private Thread1Test t1;
    public Thread2Test(Thread1Test thread1Test){
        this.t1 = thread1Test;
    }
    public void run(){
        System.out.println("thread2 開始執行");
        // t2 ...do something;
        try {
            System.out.println("thread2 開始等待 t1執行");
            t1.join(2000);
            System.out.println("t1執行結束 thread2 開始繼續執行");
            //Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("thread2 執行結束");
    }
}
public class Thread3Test extends Thread{

    private Thread2Test t2;
    private Thread4Test t4;
    public Thread3Test(Thread2Test thread2Test,Thread4Test thread4Test){
        this.t2 = thread2Test;
        this.t4 = thread4Test;
    }

    public void run(){
        System.out.println("thread3 開始執行");
        // t3 ...do otherthing;
        try {
            t4.start();
            System.out.println("thread3 開始等待 t2執行");
            t2.join();
            t4.join();

            System.out.println("t2 執行結束 thread3 繼續執行");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("thread3 執行結束");
    }
}
public class Thread4Test extends Thread{

    public void run(){
        System.out.println("thread4 開始執行");
        try {
            Thread.sleep(4000);//do something
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("thread4 執行結束");
    }

}
public class ThreadMain {

    public static void main(String[] args) throws InterruptedException {
        Thread1Test t1 = new Thread1Test();
        Thread2Test t2 = new Thread2Test(t1);
        Thread4Test t4 = new Thread4Test();
        Thread3Test t3 = new Thread3Test(t2,t4);
        System.out.println("main 線程開始執行");
        t1.start();
        t2.start();
        t3.start();
        t3.join();//main 線程會等待線程3執行結束後 才結束
        System.out.println("main 線程執行結束");
    }

}

運行結果如下:

main 線程開始執行
thread1 開始執行
thread2 開始執行
thread2 開始等待 t1執行
thread3 開始執行
thread3 開始等待 t2執行
thread4 開始執行
thread1 執行結束
t1執行結束 thread2 開始繼續執行
thread2 執行結束
thread4 執行結束
t2 執行結束 thread3 繼續執行
thread3 執行結束
main 線程執行結束


從運行結果可以看出:t1和t2依次運行,t2和t4運行結束後,t3開始繼續運行,最後是main線程執行結束

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章