【问题标题】:Why does ExecutorService waits for all threads to complete but Completable future not? [duplicate]为什么 ExecutorService 等待所有线程完成但 Completablefuture 没有? [复制]
【发布时间】:2021-09-20 11:23:03
【问题描述】:

在以下代码中,

class MainX {

    static void run(int i) {
        try {
            System.out.println(i + " called");
            Thread.sleep(1000);
            String s = "";
            for (int j = 0; j < 20000; j++) {
                s = s + j;
            }
            System.out.println(i + " completed" + " " + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            int p = i;
            executorService.submit(() -> MainX.run(p));
        }
        System.out.println("all called");
        executorService.shutdown();
        System.out.println("all called" + " Thr:" + Thread.currentThread().getName());
    }
}

(Vs)

class MainX {

    static void run(int i) {
        try {
            System.out.println(i + " called");
            Thread.sleep(1000);
            String s = "";
            for (int j = 0; j < 20000; j++) {
                s = s + j;
            }
            System.out.println(i + " completed" + " " + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        for(int i = 0; i < 10; i++) {
            int p = i;
            CompletableFuture.runAsync(() -> MainX.run(p));
        }
    }
}

在第一种情况下,jvm 会继续运行,直到所有线程都完成。但是在第二种情况下,一旦主线程死亡,jvm和其他线程就会被杀死。

有什么原因吗?

【问题讨论】:

    标签: java asynchronous java-8 executorservice completable-future


    【解决方案1】:

    在我看来,“CompletableFuture”本身并不执行任何操作,因此它没有等待线程。它依赖于其他机制来运行阶段。

    'runAsync',没有 Executor,在其公共 ForkJoin 池中运行任务,documented 具有您观察到的行为。

    这并不能回答您关于“为什么”的问题,只是说它是故意这样设计的。我只能挥手说它的设计者可能认为它是最好的默认选择。

    (我同意:在我编写的代码中,如果我到了程序终止的地步,我想要的是让一切都消失。在极少数情况下我需要它完成,我会等待在退出之前。)

    【讨论】:

    • @ManikandanKbk 因为ForkJoinPool 默认使用守护线程,而Executors 中的大多数工厂方法(不使用ThreadFactory)返回使用非守护线程的线程池线程。我已将问题作为重复问题关闭,但如果您认为目标没有回答您的问题,请告诉我。
    • 感谢 Slaw,在另一个 stackoverflow 线程中提供了非常全面的答案。现在,我要阅读有关守护程序与非守护程序的内容以及为什么有两种类型的线程等。
    猜你喜欢
    • 1970-01-01
    • 2015-02-14
    • 2018-09-22
    • 2019-10-24
    • 1970-01-01
    • 2011-03-17
    • 2010-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多