Thread 之 join() 方法

发布时间 2024-01-10 17:03:30作者: 变体精灵

案例代码

@Slf4j
public class JoinDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            log.info("{} 线程启动", Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("{} 线程执行任务", Thread.currentThread().getName());
        }, "t1");

        Thread t2 = new Thread(() -> {
            log.info("{} 线程启动", Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("{} 线程执行任务", Thread.currentThread().getName());
        }, "t2");

        t1.start();
        t2.start();
        log.info("{} 线程执行任务", Thread.currentThread().getName());
    }
}

从上面的结果可以看出,main 线程首先获取到了 CPU 的时间片,然后执行,接着 t2 和 t1 获取到 CPU 时间片,获得执行

如果我们想 main 线程在 t1 和 t2 线程执行完任务之后再去执行 main 线程的任务,那该怎么办呢,这个时候就可以使用线程类提供的 join 方法了

@Slf4j
public class JoinDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            log.info("{} 线程启动", Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("{} 线程执行任务", Thread.currentThread().getName());
        }, "t1");

        Thread t2 = new Thread(() -> {
            log.info("{} 线程启动", Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("{} 线程执行任务", Thread.currentThread().getName());
        }, "t2");

        t1.start();
        t2.start();

        // 在主线程中分别调用 t1、t2 线程的 join() 方法,那么主线程就会等待 t1 和 t2 线程执行完毕之后再去执行主线程自身的任务
        t1.join();
        t2.join();

        log.info("{} 线程执行任务", Thread.currentThread().getName());
    }
}

使用 join 方法之后,main 线程会等待 t1、t2 线程执行完成自身的任务之后,接着才会去执行 main 线程的任务

上面我们使用的是 join() 的无参方法,无参的 join 方法实际上就是等价于 join(0)

接着我们看一下这个有参的 join 方法

如果传递进来的参数大于 0,底层实际上是调用 wait(delay),这个方法的作用是只会做有时限的等待,过时不候

@Slf4j
public class JoinDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            log.info("{} 线程启动", Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("{} 线程执行任务", Thread.currentThread().getName());
        }, "t1");

        t1.start();

        // 只会做有时限的等待,如果等待的时间超过了 t1 线程的执行时间,那么就不再继续等待了
        t1.join(2000);

        log.info("{} 线程执行任务", Thread.currentThread().getName());
    }
}

从执行结果中可以看出,main 线程只等待了 2000ms,然后就开始执行 main 线程的任务去了,此时 t1 线程还没有执行完毕,main 线程就停止了等待