用途
Thread.join() 方法表示线程让步,在 t1 线程中调用 t2 线程的 join() 方法,表示让 t1 线程进行等待,待 t2 线程执行完毕后,t1 线程继续执行。
源码解析
join 方法的源码如下:
1 | public final synchronized void join(final long millis) |
可以看到该方法由 synchronized 关键字修饰。synchronized 修饰一个方法,锁住的是当前实例对象。当在 t1 线程中调用 t2.join() 时,其实是将 t2 对象作为锁,t1 线程需要获取到 t2 对象的监视器锁(Monitor),才能执行 join() 方法中的逻辑。
进入 join() 方法后,根据时间参数执行不同的逻辑:
- 如果时间参数小于 0,会抛出非法参数的异常。
- 时间参数等于 0,不停检查 t2 线程是否存活,如果 t2 线程存活,则释放 t2 对象的监视器锁,挂起当前线程,即 t1 线程,t1 线程进入 WAITING 状态。
- 时间参数大于 0,t1 线程每次挂起时,都会重新计算等待时间,直到等待时间小于等于0,或者线程 t2 结束。
当线程 t2 执行结束,JVM 底层自动触发 t2.notifyAll(),唤醒所有在 t2 对象上等待的线程,线程 t1 被唤醒后,重新获取 t2 对象的锁,while() 结束,join() 结束,继续执行 t2.join() 后的逻辑。
注意点
- 阻塞的调用它的线程。比如 t1.join(),表示阻塞当前线程,而 t1 正常执行。
- join() 方法必须在调用 start() 方法之后调用,如果在 start() 方法之前调用,由于 isAlive() 会直接 false,不会有等待的效果。
- join(final long millis) 方法参数传 0 相当于不传参数,表示无限期等待,而不是等待 0 毫秒。