join:线程加塞。
官方释义:Waits for this thread to die.(等待当前线程死掉)
join()方法是java.lang.Thread类的成员方法,因此只有Thread的实例可以调用。
join的用法实例:
/**
* Thread的join()线程加塞方法测试
*/
public class Join {
@Test
public void test(){
Thread joinThread = new Thread(new Runnable() {
@Override
public void run() {
b();
}
});
new Join().a(joinThread);
}
public void a(Thread joinThread){
System.out.println("a方法被调用");
joinThread.start();
try {
joinThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("a方法执行完毕");
}
public void b(){
System.out.println("b方法被调用");
System.out.println("b方法执行完毕");
}
运行结果:
结果分析:
在主线程中加塞,可见主线程是等到加塞线程死掉后才运行加塞线程后的代码。
源码分析:java.lang.Thread join()方法的源码
/**
* Waits at most {@code millis} milliseconds for this thread to
* die. A timeout of {@code 0} means to wait forever.
*
* <p> This implementation uses a loop of {@code this.wait} calls
* conditioned on {@code this.isAlive}. As a thread terminates the
* {@code this.notifyAll} method is invoked. It is recommended that
* applications not use {@code wait}, {@code notify}, or
* {@code notifyAll} on {@code Thread} instances.
*
* @param millis
* the time to wait in milliseconds
*
* @throws IllegalArgumentException
* if the value of {@code millis} is negative
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
*/
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) {
// 如果子线程还活着,就继续等待,这里的wait是主线程等待,不是加塞线程,因为synchronized是加在方法上的,锁的是当前调用方法的对象,当前调用方法的对象是加塞线程的实例,而调用的地方是主线程里面,相当于在主线程中执行了obj.wait(),只不过此时的obj是一个加塞线程对象而已。
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
那么何时这个wait被notify呢? 官方注释有描述
As a thread terminates the {@code this.notifyAll} method is invoked
当一个线程运行结束时,this.notifyAll方法会被调用,也就是当加塞线程运行完毕是,加塞线程对象的notifyAll方法会被调用,恰好主线程中的锁对象是加塞线程的对象,所以此时主线程被唤醒。
如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
-
点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
-
关注公众号 『逆行的碎石机』,不定期分享原创知识。
-
同时可以期待后续文章ing🚀