把之前CompletableFuture留下的坑给填上。

你好呀,我是歪歪。

填个坑吧,把之前一直欠着的 CompletableFuture 给写了,因为后台已经收到过好几次催更的留言了。

这玩意我在之前写的这篇文章中提到过:《面试官问我知不知道异步编程的Future》

因为是重点写 Future 的,所以 CompletableFuture 只是在最后一小节的时候简单的写了一下:

把之前CompletableFuture留下的坑给填上。

我就直接把当时的例子拿过来改一下吧,先把代码放在这里了:

public class MainTest {

    public static void main(String[] args) throws Exception {
        CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "-女神:我开始化妆了,好了我叫你。");
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "化妆完毕了。";
        }).whenComplete((returnStr, exception) -> {
            if (exception == null) {
                System.out.println(Thread.currentThread().getName() + returnStr);
            } else {
                System.out.println(Thread.currentThread().getName() + "女神放你鸽子了。");
                exception.printStackTrace();
            }
        });
        System.out.println(Thread.currentThread().getName() + "-等女神化妆的时候可以干点自己的事情。");
        Thread.currentThread().join();
    }
}

核心需求就是女神化妆的时候,我可以先去干点自己的事情。

上面的程序运行结果是这样的:

把之前CompletableFuture留下的坑给填上。

符合我们的预期,没有任何毛病。

但是当你自己去编写程序的时候,有可能会遇到这样的情况:

把之前CompletableFuture留下的坑给填上。

什么情况,女神还在化妆呢,程序就运行完了?

把之前CompletableFuture留下的坑给填上。

是的,这就是我要说的第一个关于 CompletableFuture 的知识点:守护线程。

守护线程

你仔细观察前面提到的两个截图,对比一下他们的第 28 行,第二个截图少了一行代码:

Thread.currentThread().join();

这行代码是在干啥事呢?

目的就是阻塞主线程,哪怕你让主线程睡眠也行,反正目的就是把主线程阻塞住。

如果没有这行代码,出现的情况就是主线程直接运行完了,程序也就结束了。

你想想,会是什么原因?

这个时候你脑海里面应该啪的一下,很快就想到“守护线程”这个概念。

主线程是用户线程,这个没啥说的。

所有的用户线程执行完成后, JVM 也就退出了。

因此,出现上面问题的原因我有合理的理由猜测:CompletableFuture 里面执行的任务属于守护线程。

有了理论知识的支撑,并推出这个假设之后,就有了证实的方向,问题就很简单了。

啪的一下在这里打上一个断点,然后 Debug 起来,表达式一写就看出来了,确实是守护线程:

把之前CompletableFuture留下的坑给填上。

我一般是想要看到具体的代码的,就是得看到把这个线程设置为守护线程的那一行代码,我才会死心。

所以我就去找了一下,还是稍微花了点时间,过程就不描述了,直接说结论吧。

首先 CompletableFuture 默认的线程池是 ForkJoinPool,这个是很容易就能在源码里面找到的:

把之前CompletableFuture留下的坑给填上。

在 ForkJoinPool 里面,把线程都设置为守护线程的地方就在这里:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwpzdf.html