CompletableFuture需要更多的时间-Java8

CompletableFuture需要更多的时间-Java8,java,java-8,future,completable-future,Java,Java 8,Future,Completable Future,我有两段技术上相同的代码,但第二段比第一段多花1秒钟。第一个在6秒内执行,第二个在7秒内执行 Double yearlyEarnings = employmentService.getYearlyEarningForUserWithEmployer(userId, emp.getId()); CompletableFuture<Double> earlyEarningsInHomeCountryCF = currencyConvCF.thenApplyAsync(currencyC

我有两段技术上相同的代码,但第二段比第一段多花1秒钟。第一个在6秒内执行,第二个在7秒内执行

Double yearlyEarnings = employmentService.getYearlyEarningForUserWithEmployer(userId, emp.getId());

CompletableFuture<Double> earlyEarningsInHomeCountryCF = currencyConvCF.thenApplyAsync(currencyConv -> {
  return currencyConv * yearlyEarnings;
});

你的问题非常不完整,但从我们的猜测来看,第二种变体可能需要更长的时间,如果我们假设
currencyConvCF
表示一个异步操作,该操作可能在执行代码片段时并发运行,您所说的是完成所有操作所需的总时间,包括由
thenApplyAsync
返回的
CompletableFuture
表示的操作(
EarldGranningsinhomeCountrycf

在第一个变量中,您正在调用
getYearlyEarningForUserWithEmployer
,而
currencyConvCF
表示的操作可能仍在同时运行。两个操作完成后,将发生乘法

在第二个变体中,
getYearlyEarningForUserWithEmployer
调用是传递给
currencyConvCF的操作的一部分。然后applyasync
,因此它在
currencyConvCF
表示的操作完成之前不会启动,因此不会同时运行任何操作。如果假定
getYearlyEarningForUserWithEmployer
需要很长的时间,比如说一秒钟,并且与另一个操作没有内部依赖关系,因此在该变体中,整个操作需要更长的时间也就不足为奇了

看起来,你真正想做的是:

CompletableFuture<Double> earlyEarningsInHomeCountryCF = currencyConvCF.thenCombineAsync(
    CompletableFuture.supplyAsync(
        () -> employmentService.getYearlyEarningForUserWithEmployer(userId, emp.getId())),
    (currencyConv, yearlyEarnings) -> currencyConv * yearlyEarnings);

霍尔格所说的都是有道理的,但在我发布的问题中却没有。我同意这个问题不是用最好的方式写的

问题在于,期货交易的顺序导致了时间的持续增长

理想情况下,只要代码是以正确的反应方式编写的,未来的顺序就不重要

问题的原因是Java的默认ForkJoinPool,Java在默认情况下使用该池运行所有CompletableFutures。如果使用自定义池运行所有CompletableFutures,则无论future语句的编写顺序如何,我都会得到几乎相同的时间

我仍然需要找到ForkJoinPool的局限性,以及为什么我的定制池(20个线程)性能更好


当我找到正确的原因时,我会更新我的答案。

你能给出employmentService.getYearlyEarningForUserWithEmployer()的一个片段吗?它有什么不同?请做一个。你能在问题本身中发布它吗?最好简化变量名称并给出完整的示例,以便我们可以从外部复制它
Double getYearlyEarningForUserWithEmployer(long userId, long employerId);
CompletableFuture<Double> earlyEarningsInHomeCountryCF = currencyConvCF.thenCombineAsync(
    CompletableFuture.supplyAsync(
        () -> employmentService.getYearlyEarningForUserWithEmployer(userId, emp.getId())),
    (currencyConv, yearlyEarnings) -> currencyConv * yearlyEarnings);
CompletableFuture<Double> currencyConvCF = /* a true asynchronous operation */
return employmentService.getYearlyEarningForUserWithEmployer(userId, emp.getId())
     * employerCurrencyCF.join();