在實際開發中我們往往會遇到這樣的情況一個線程的執行需要依賴另一個線程執行後的結果。即主線程生成並起動了子線程,如果子線程裡要進行大量的耗時的運算,主線程往往將於子線程之前結束,但是如果主線程處理完其他的事務後,需要用到子線程的處理結果,也就是主線程需要等待子線程執行完成之後再結束,這個時候就要用到join()方法了。
join() 方法主要是讓調用該方法的thread完成run方法裡面的任務後, 再執行join()方法後面的代。
主線程生成並起動了子線程,而子線程裡要進行大量的耗時的運算(這裡可以借鑒下線程的作用),當主線程處理完其他的事務後,需要用到子線程的處理結果,這個時候就要用到join();方法了。
//該方法會無限等待,它會一直阻塞當前線程直到目標線程(調用該方法的線程)執行完畢。
public final void join() throws InterruptedException { join(0); }
//該方法需要給出最大等待時間,如果目標線程的執行時間超過給定的時間,那麼當前線程將不在等待目標線程執行結束而直接執行
public final synchronized void join(long millis)throws InterruptedException{}
public class ThreadJoinTest {
private static String str=null;
public static void main(String[] args) {
Thread thread=new Thread(){
@Override
public void run() {
try {
System.out.println("進入"+Thread.currentThread().getName()+"線程");
Thread.sleep(1000);
str="hello Word";
System.out.println(Thread.currentThread().getName()+"線程業務處理完畢");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
try {
//thread.join();//設置main線程等待子線程先處理業務
System.out.println(Thread.currentThread().getName()+"線程處理業務開始");
System.out.println("獲取str值:"+str);
} catch (Exception e) {
e.printStackTrace();
}
}
}
執行結果:
main線程處理業務開始
進入Thread-0線程
獲取str值:null
Thread-0線程業務處理完畢
運行代碼,貌似永遠都看不到str的值是"hello Word",而每次都是null,原因很簡單的,因為在thread中的run方法中對str進行賦值操作前休眠了1秒,此時main線程中的System.out.println方法已經執行了,所以很難看到str的值是"hello Word",為了看到str的值是"hello Word",我們的一個思路就是等thread運行結束之後,我們再執行System.out.println就可以了,這時候join方法的作用就顯現出來的,我們把上面的注釋代碼刪除注釋,然後運行,不管運行多少次,輸出的結果都是“hello Word”,從這個例子中我們就可以看到join方法的作用,它能夠調節各個線程之間的運行順序,從而可以實現同步。
如果修改注釋的代碼為thread.join(100);則執行結果為:獲取str值:null ,因為主線程已經等不及了。
join()他讓調用線程在當前線程對象上進行等待當線程執行完畢後,被等待的線程會在推出前調用notifyAll()方法通知所有的等待線程繼續執行。
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;
}
}
}