Java中Thread類提供join()方法。
作用:用於在當前線程A中添加別的線程B,這時線程A被阻塞,處於Blocked狀態,線程B開始執行,當線程B執行完以後,線程A處於可運行狀(Runnable),等待cpu的調度再執行。
用法:當前線程A必須先用myThread的start()啓動線程(否則join()不會被執行),然後調用join():
//線程A中的代碼
myThread.start();
myThread.join();
//線程A中的代碼
實例:
1. 實現Runnable接口,重寫run方法
public class MyTask implements Runnable {
private int taskNum;
private Thread thread = null;
public MyTask(int num) {
this.taskNum = num;
}
public MyTask(int num, Thread thread) {
this.taskNum = num;
this.thread = thread;
}
@Override
public void run() {
System.out.println("正在執行task " + taskNum);
try {
if (thread != null) {
System.out.println("join的線程開始執行");
thread.start();//****在當前線程中啓動要添加的線程****//
thread.join();//****執行join()方法****//
System.out.println("join的線程執行完畢");
System.out.println("繼續執行當前線程");
}
Thread.sleep(taskNum * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task " + taskNum + " 執行完畢");
}
}
- 編寫測試類:
public class Main {
public static void main(String[] args) throws InterruptedException {
System.out.println(Thread.currentThread().getName() + "開始執行");
Thread thread2 = new Thread(new MyTask(10));
Thread thread1 = new Thread(new MyTask(5, thread2));
thread1.start();
thread1.join();
System.out.println(Thread.currentThread().getName() + "執行完畢");
}
}
在main線程中添加thread1線程,main線程被阻塞,thread1開始執行;
thread1中有添加了thread2線程,thread將被阻塞,直到thread2執行完畢;
3. 結果:main開始執行–>task1開始執行–>task2開始執行–>task2執行完畢–>task1執行完畢–>main執行完畢
main開始
正在執行task 1
join的線程開始執行
正在執行task 2
task 2 執行完畢
join的線程執行完畢
繼續執行當前線程
task 1 執行完畢
main執行完畢
4. JDK中join()的實現
public final void join() throws InterruptedException {
join(0);
}
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()) {//****表明如果myThread.join()中的myThread執行完畢變成dead狀態,則退出循環,返回調用myThread.join()的線程繼續執行
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
所以有兩種方式調用join()方法:
(1).myThread.join();//不指定當前線程wait的時間,這會導致當前線程一直阻塞至myThread執行完畢
(2).myThread.join(long time);//指定當前線程wait時間,這回導致當前線程一直阻塞time毫秒或者myThread執行完畢
5. 測試join(long time)
修改上文的MyTask類
public class MyTask implements Runnable {
private int taskNum;
private Thread thread = null;
public MyTask(int num) {
this.taskNum = num;
}
public MyTask(int num, Thread thread) {
this.taskNum = num;
this.thread = thread;
}
@Override
public void run() {
System.out.println("正在執行task " + taskNum);
try {
if (thread != null) {
System.out.println("join的線程開始執行");
long start = System.currentTimeMillis();
thread.start();
thread.join(3000);
long end = System.currentTimeMillis();
System.out.println("join的線程執行完畢,用時" + (end - start) + "毫秒");
System.out.println("繼續執行當前線程");
}
Thread.sleep(taskNum * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task " + taskNum + " 執行完畢");
}
}
- 結果
main開始執行
正在執行task 1
join的線程開始執行
正在執行task 2
task 2 執行完畢
join的線程執行完畢,用時2000毫秒//表明join的線程執行完畢以後就返回了
繼續執行當前線程
task 1 執行完畢
main執行完畢