发布时间:2025-12-09 12:02:42 浏览次数:1
关于join官方的解释是 Waits for this thread to die. 也就是等待一个线程结束。可以通过对另一个线程对象调用join()方法可以等待其执行结束,然后才继续往下执行自身线程。
public class Main { public static void main(String[] args) { Thread t1 = new Thread(() -> { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName()+"线程执行..."+i); } },"T1"); t1.start(); for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName()+"线程执行..."+i); } }}...T1线程执行...81T1线程执行...82main线程执行...50T1线程执行...83T1线程执行...84main线程执行...51main线程执行...52T1线程执行...85T1线程执行...86main线程执行...53main线程执行...54T1线程执行...87...可以看到正常两个线程是交替执行的。如果我们想线程t1执行完再执行main线程呢,这里就需要使用join了:
public class Main { public static void main(String[] args) { Thread t1 = new Thread(() -> { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName()+"线程执行..."+i); } },"T1"); t1.start(); // 调用t1的join方法,当前线程等待,等待t1线程执行后再执行当前线程 try { t1.join(); } catch (InterruptedException e) { e.printStackTrace(); } for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName()+"线程执行..."+i); } }}执行效果:
....T1线程执行...90T1线程执行...91T1线程执行...92T1线程执行...93T1线程执行...94T1线程执行...95T1线程执行...96T1线程执行...97T1线程执行...98T1线程执行...99main线程执行...0main线程执行...1main线程执行...2main线程执行...3main线程执行...4main线程执行...5main线程执行...6....此时子线程T1执行完之后才执行main线程。
join方法还支持几个参数:
现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完之后执行,T3在T2执行完后执行?
使用join是最简单的方案,实现的代码如下:
/** * @author wcc * @date 2021/8/21 20:46 * 现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行? */public class JoinDemo { public static void main(String[] args) { Thread t1=new Thread(new Runnable() { @Override public void run() { System.out.println("t1 is running..."); } }); //初始化线程二 Thread t2=new Thread(new Runnable() { @Override public void run() { try { // 调用t1的join,意味着再t1执行后,才执行此线程 t1.join(); } catch (InterruptedException e) { e.printStackTrace(); }finally { System.out.println("t2 is running..."); } } }); //初始化线程三 Thread t3=new Thread(new Runnable() { @Override public void run() { try { // 调用t2的join,意味着再t1执行后,才执行此线程 t2.join(); } catch (InterruptedException e) { e.printStackTrace(); }finally { System.out.println("t3 is running..."); } } }); t1.start(); t2.start(); t3.start(); }}执行结果:
t1 is running...t2 is running...t3 is running...在t2线程中t2本身就是调用线程,所谓的调用线程是指调用了t.join()方法的线程,而被调用的对象指的是调用join方法的线程对象,即t1。*所以这三个线程按照*t1 -> t2 -> t3的顺序执行了。
/** * 等待该线程终止的时间最长为millis毫秒,超时时间为0意味着要一直等下去 * @param millis 以毫秒为单位的等待时间 * @throws InterruptedException */ public final synchronized void join(long millis) throws InterruptedException { //获取启动的时间戳,用于计算当前时间 long base = System.currentTimeMillis(); //当前时间 long now = 0; if (millis < 0) { //等待时间不能小于0 否则抛出IllegalArgumentException异常终止程序 throw new IllegalArgumentException("timeout value is negative"); }//判断是否携带阻塞的超时时间,等于0则表示没有设置超时时间 //如果超时时间为0 则意味着一直要等待该线程执行完(无限等待) if (millis == 0) { //需要注意的是,如果当前线程未被启动或者已经终止,则isAlive方法返回false //即意味着join方法不会生效 while (isAlive()) { //isAlive()方法:判断当前线程是否处于活动状态 //活动状态就是线程已经启动并且尚未终止 wait(0); } } else { //设置了超时时间 //需要注意的是,如果当前线程未被启动或者已经终止,则isAlive方法返回false //即意味着join方法不会生效 while (isAlive()) {, //计算剩余时间 long delay = millis - now; if (delay <= 0) { //如果剩余等待的时间小于等于0,则终止等待 break; } //等待指定时间 wait(delay); //获取此次循环执行的时间 now = System.currentTimeMillis() - base; } } }