为什么CompletableFuture.supplyAsync成功随机次数? [英] Why is CompletableFuture.supplyAsync succeeding a random number of times?

查看:132
本文介绍了为什么CompletableFuture.supplyAsync成功随机次数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Java 8中的lambdas和异步代码的新手。我不断得到一些奇怪的结果......

I'm new to both lambdas and asynchronous code in Java 8. I keep getting some weird results...

我有以下代码:

import java.util.concurrent.CompletableFuture;

public class Program {

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            String test = "Test_" + i;
            final int a = i;

            CompletableFuture<Boolean> cf = CompletableFuture.supplyAsync(() -> doPost(test));
            cf.thenRun(() -> System.out.println(a)) ;
        }
    }

    private static boolean doPost(String t) {
        System.out.println(t);

        return true;
    }
}

实际代码要长得多,因为 doPost 方法会将一些数据发布到Web服务。但是,我能用这个简单的代码复制我的问题。

The actual code is a lot longer, as the doPost method will post some data to a web service. However, I'm able to replicate my issue with this bare-bones code.

我想要 doPost 方法执行100次,但出于性能原因异步(为了将数据推送到Web服务的速度比执行100次同步调用的速度快)。

I want to have the doPost method execute 100 times, but asynchronously for performance reasons (in order to push data to the web service faster than doing 100 synchronous calls would be).

在上面的代码中,'doPost'方法是随机运行的,但总是不超过20-25次。没有异常抛出。似乎某些线程处理机制默默地拒绝创建新线程并执行它们的代码,或者线程在没有崩溃程序的情况下静默崩溃。

In the code above, the ´doPost´ method is run a random amount of times, but always no more than 20-25 times. There are no exceptions thrown. It seems that either some thread handling mechanism is silently refusing to create new threads and execute their code, or the threads are silently crashing without crashing the program.

我也有一个问题在于,如果我向 doPost 方法添加比上面显示的更多的功能,它会达到方法只是默默地中断的程度。在这种情况下,我尝试在return语句之前添加一个 System.out.println(test),但它永远不会被调用。循环100次的循环确实运行了100次迭代。

I also have an issue where, if I add more functionality to the doPost method than shown above, it reaches a point where the method simply silently breaks. I've tried adding a System.out.println("test") right before the return statement in that case, but it is never called. The loop which loops 100 times does run 100 iterations though.

这种行为令人困惑,至少可以说。

This behaviour is confusing, to say the least.

我错过了什么?为什么作为参数提供的函数 supplyAsync 运行一个看似随机的次数?

What am I missing? Why is the function supplied as an argument to supplyAsync run a seemingly random number of times?

编辑:只是想指出情况与问题中的情况不完全相同,因为这个问题涉及任意深度嵌套的期货,而这一问题涉及平行的问题。然而,他们失败的原因几乎完全相同。案件看起来很明显,值得我提出不同的问题,但其他人可能不同意......

推荐答案

默认情况下 CompletableFuture 使用自己的 ForkJoinPool.commonPool()(参见 CompletableFuture 实现)。此默认池仅创建守护程序线程,例如他们不会阻止主要应用程序终止,如果他们还活着。

By default CompletableFuture uses own ForkJoinPool.commonPool() (see CompletableFuture implementation). And this default pool creates only daemon threads, e.g. they won't block the main application from terminating if they still alive.

您有以下选择:


  1. 收集所有 CompletionStage 到某个数组然后make java.util.concurrent.CompletableFuture #allOf() .toCompletableFuture()。join() - 这将保证所有阶段完成后再继续 join()

  1. Collect all CompletionStage to some array and then make java.util.concurrent.CompletableFuture#allOf().toCompletableFuture().join() - this will guarantee all the stages are completed before going after join()

对您自己的线程池使用 * Async 操作,该线程池仅包含非守护进程线程,如下例所示:

Use *Async operations with your own thread pool which contains only non-daemon threads, like in the following example:

public static void main(String[] args) throws InterruptedException {
    ExecutorService pool = Executors.newFixedThreadPool(10, r -> {
        Thread t = new Thread(r);
        t.setDaemon(false); // must be not daemon
        return t;
    });

    for (int i = 0; i < 100; i++) {
        final int a = i;

        // the operation must be Async with our thread pool
        CompletableFuture<Boolean> cf = CompletableFuture.supplyAsync(() -> doPost(a), pool);
        cf.thenRun(() -> System.out.printf("%s: Run_%s%n", Thread.currentThread().getName(), a));
    }

    pool.shutdown(); // without this the main application will be blocked forever
}

private static boolean doPost(int t) {
    System.out.printf("%s: Post_%s%n", Thread.currentThread().getName(), t);

    return true;
}


这篇关于为什么CompletableFuture.supplyAsync成功随机次数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆