Thread 之 join() 方法

案例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@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 方法了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@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),这个方法的作用是只会做有时限的等待,过时不候

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@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 线程就停止了等待

 

posted @   变体精灵  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 我与微信审核的“相爱相杀”看个人小程序副业
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~
点击右上角即可分享
微信分享提示