目录
1、join()简介
join()方法的作用在一个线程内调用另一个线程实例的join()方法,表示线程在此阻塞,以等待相应的实例执行完成,join()内部是通过wait()方法实现的,因此调用join会自动释放锁
2、例子
public class ThreadDemo extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " begin run");
long startTime = System.currentTimeMillis();
try {
//模拟耗时处理
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName() + "执行时间为:" + (endTime - startTime));
System.out.println(Thread.currentThread().getName() + "end run");
}
}
public class RunTest {
public static void main(String[] args) throws InterruptedException {
Thread.currentThread().setName("主线程");
System.out.println(Thread.currentThread().getName() + "begin run");
ThreadDemo threadDemo = new ThreadDemo();
threadDemo.setName("子线程");
threadDemo.start();
//阻塞等待
threadDemo.join();
System.out.println(Thread.currentThread().getName() + "end run");
}
}
运行结果:
从结果中我们可以看出,主线程调用子线程,当执行到join()方法时,子线程对象进入阻塞队列,待子线程执行完毕后主线程继续执行。
3、底层原理
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) {//若millis小于0则抛出异常
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {//若millis=0
while (isAlive()) {//判断当前线程是否存活
wait(0);//永久等待,直到线程销毁
}
} else {//millis大于0,阻塞指定时间,若时间过期,线程还未结束,就不等待了
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
从源码可知,当参数millis为0时,while循环使用isAlive()方法判断当前线程是否存活(线程存活是指线程已经启动并且还没有死亡),wait(0)表示永远等待。
注意,我们在源码中看到只有wait()方法,却没看到notify()方法,那么是由谁去唤醒在阻塞池中的线程呢?这个是在jvm中实现的, 一个线程执行结束后会执行该线程自身对象的notifyAll方法。
4、其他方法
- join(long millis):等待执行毫秒,到时后就不等待了
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;
}
}
}
- join(long millis, int nanos):等待最多为millis+1毫秒,最少为1毫秒
public final synchronized void join(long millis, int nanos)
throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
//当nanos大于500微妙时,或者毫秒值=0,则等待时间为millis+1毫秒值,至少为1毫秒
millis++;
}
join(millis);
}