Join 方法详解
join()
用来等待一个线程的结束,是一种比较”暴力“的线程同步机制,必须等到一个线程结束后另一个线程才开始执行接下来的代码。同时,
join(3000)
指定最长等待时间,如果等待时间超过指定的最长等待时间,那么会直接执行下面的方法。
默认无限等待
测试案例1
import java.util.concurrent.TimeUnit;
public class JoinMain {
public static void main(String[] args) {
Thread threadA = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
System.out.println("线程被唤醒");
}
}, "threadA");
Thread threadB = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
System.out.println("线程被唤醒");
}
}, "threadB");
long begin = System.currentTimeMillis();
System.out.println("begin: " + begin);
threadA.start();
threadB.start();
// threadA在sleep的时候, threadB也在sleep
try {
//-------假设threadA和threadB都已经出于running运行态阶段
threadA.join();
//-------此时threadA和threadB都已经睡眠1s
threadB.join();
//-------threadB再睡眠1s, 主线程便可以执行后面的逻辑
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
long end = System.currentTimeMillis();
System.out.println("end: " + end);
// 输出结果约等于2s
System.out.println("run time cost is: " + (end - begin));
}
}
测试案例2
import java.util.concurrent.TimeUnit;
public class JoinMain {
public static void main(String[] args) {
Thread threadA = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
System.out.println("线程被唤醒");
}
}, "threadA");
Thread threadB = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
System.out.println("线程被唤醒");
}
}, "threadB");
long begin = System.currentTimeMillis();
System.out.println("begin: " + begin);
// threadA在sleep的时候, threadB也在sleep
try {
threadA.start();
//-------假设threadA已经出于running运行态阶段
threadA.join();
//-------此时threadA已经睡眠1s, 主线程可以执行启动threadB的代码
threadB.start();
//-------假设threadB已经出于running运行态阶段
threadB.join();
//-------threadB睡眠2s, 主线程便可以执行后面的逻辑
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
long end = System.currentTimeMillis();
System.out.println("end: " + end);
// 输出结果约等于3s
System.out.println("run time cost is: " + (end - begin));
}
}
总结:join()
方法执行后,如果不满足条件,则调用线程阻塞,不会执行 join()
方法后面的代码。
指定最长等待时间
最长等待时间并不是必须等待指定时间,而是如果在该指定时间内还没结束,则不再等待;如果在该指定时间内结束,也可以执行下面的流程。
测试案例3
import java.util.concurrent.TimeUnit;
public class JoinMain {
public static void main(String[] args) {
Thread threadA = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
System.out.println("线程被唤醒");
}
}, "threadA");
Thread threadB = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
System.out.println("线程被唤醒");
}
}, "threadB");
long begin = System.currentTimeMillis();
System.out.println("begin: " + begin);
// threadA在sleep的时候, threadB也在sleep
try {
threadA.start();
//-------假设threadA已经出于running运行态阶段
threadA.join();
//-------此时threadA已经睡眠1s, 主线程可以执行启动threadB的代码
threadB.start();
//-------假设threadB已经出于running运行态阶段
threadB.join(3000);
//-------threadB睡眠2s, join(3000)至多等待3s, 任一条件满足即可, 因此阻塞时间为: min(max_wait_time, thread_run_time);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
long end = System.currentTimeMillis();
System.out.println("end: " + end);
// 输出结果约等于3s
System.out.println("run time cost is: " + (end - begin));
}
}