Thread的Join方法

发布时间:2025-12-09 12:02:42 浏览次数:1

目录
  • 简述
  • join场景
  • Join方法
  • join的使用实例
  • join原理

简述

关于join官方的解释是 Waits for this thread to die. 也就是等待一个线程结束。可以通过对另一个线程对象调用join()方法可以等待其执行结束,然后才继续往下执行自身线程。

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方法

join方法还支持几个参数:

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的顺序执行了。

join原理

/**     * 等待该线程终止的时间最长为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;            }        }    }
  1. 如果想要join方法正常生效,调用join方法的线程对象必须已经调用了start()方法并且未进入终止状态。
  2. join方法的本质调用的是Object中的wait方法实现线程的阻塞。
  3. Thread.join其实底层是通过wait/notifyall来实现线程的通信达到线程阻塞的目的;当线程执行结束以后,会触发两个事情,第一个是设置native线程对象为null、第二个是通过notifyall方法,让等待在previousThread对象锁上的wait方法被唤醒。
thread.join
需要做网站?需要网络推广?欢迎咨询客户经理 13272073477