join方法爲Thread類的接口方法,它有兩種重載方式,傳空參和傳毫秒數(long millis)。這個方式表示等待這個線程死亡(最多millis秒)。舉個最簡單的例子:
public class Main {
public static void main(String[] args) {
Thread myThread1 = new Thread(new MyThread(), "子線程1");
myThread1.start();
for (int i = 0; i < 10; i++) {
System.out.println("main線程:" + i);
}
}
}
class MyThread implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
按照之前的多線程知識,main線程和sub線程將交叉打印i的值:
這時有個需求,main線程等sub線程執行完後再執行,那麼就在main線程中調用sub線程對象的join方法並捕獲異常。將main方法改爲:
public static void main(String[] args) {
Thread myThread1 = new Thread(new MyThread(), "子線程1");
myThread1.start();
try {
myThread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 10; i++) {
System.out.println("main線程:" + i);
}
}
運行結果:
原因:在sub線程啓動後,main線程中sub線程對象調用join方法,此時main線程就一直等着sub線程執行完死亡才執行自己的邏輯。這樣做又讓程序的執行方式變爲之前一條路徑執行。
現在有一個新需求,有T1,T2,T3三個線程,讓T1先執行完再執行T2,T2執行完再執行T3,那麼代碼可能是這樣:
public class Main {
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("T1:" + i);
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 10; i++) {
System.out.println("T2:" + i);
}
}
});
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 10; i++) {
System.out.println("T3:" + i);
}
}
});
t1.start();
t2.start();
t3.start();
}
}
如果main線程中還有邏輯代碼,那麼main線程中還要調用t3.join()。運行結果和單線程運行的一樣...純屬沒事找事!
//下面看一個比較簡單的多線程應用案例