Thread 之 join() 方法
案例代码
@Slf4j
public class JoinDemo {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
log.info("{} 线程启动", Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("{} 线程执行任务", Thread.currentThread().getName());
}, "t1");
Thread t2 = new Thread(() -> {
log.info("{} 线程启动", Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("{} 线程执行任务", Thread.currentThread().getName());
}, "t2");
t1.start();
t2.start();
log.info("{} 线程执行任务", Thread.currentThread().getName());
}
}
从上面的结果可以看出,main 线程首先获取到了 CPU 的时间片,然后执行,接着 t2 和 t1 获取到 CPU 时间片,获得执行
如果我们想 main 线程在 t1 和 t2 线程执行完任务之后再去执行 main 线程的任务,那该怎么办呢,这个时候就可以使用线程类提供的 join 方法了
@Slf4j
public class JoinDemo {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
log.info("{} 线程启动", Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("{} 线程执行任务", Thread.currentThread().getName());
}, "t1");
Thread t2 = new Thread(() -> {
log.info("{} 线程启动", Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("{} 线程执行任务", Thread.currentThread().getName());
}, "t2");
t1.start();
t2.start();
// 在主线程中分别调用 t1、t2 线程的 join() 方法,那么主线程就会等待 t1 和 t2 线程执行完毕之后再去执行主线程自身的任务
t1.join();
t2.join();
log.info("{} 线程执行任务", Thread.currentThread().getName());
}
}
使用 join 方法之后,main 线程会等待 t1、t2 线程执行完成自身的任务之后,接着才会去执行 main 线程的任务
上面我们使用的是 join() 的无参方法,无参的 join 方法实际上就是等价于 join(0)
接着我们看一下这个有参的 join 方法
如果传递进来的参数大于 0,底层实际上是调用 wait(delay),这个方法的作用是只会做有时限的等待,过时不候
@Slf4j
public class JoinDemo {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
log.info("{} 线程启动", Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("{} 线程执行任务", Thread.currentThread().getName());
}, "t1");
t1.start();
// 只会做有时限的等待,如果等待的时间超过了 t1 线程的执行时间,那么就不再继续等待了
t1.join(2000);
log.info("{} 线程执行任务", Thread.currentThread().getName());
}
}
从执行结果中可以看出,main 线程只等待了 2000ms,然后就开始执行 main 线程的任务去了,此时 t1 线程还没有执行完毕,main 线程就停止了等待