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执行完毕