然后在可压缩的未来中应用



在下面的代码中

public CompletableFuture<String> getMyFuture(String input)
{   
CompletableFuture<String> future = new CompletableFuture<String>().thenApply((result) -> result+ "::");
ExecutorService service = Executors.newFixedThreadPool(6);
service.submit(() -> {      
try {
future.complete(getResult(input));
} catch (InterruptedException e) {
e.printStackTrace();
}
});
return future;
}
public String getResult(String input) throws InterruptedException
{
Thread.sleep(3000);
return "hello "+ input +" :" + LocalTime.now();
}

我希望输出包含尾随的"::",但程序不是"你好先:16:49:30.231 " 我的应用实现正确吗?

您正在调用您在第一行获得的CompletionStagecomplete()方法(您称之为"thenApply"方法)。

如果你的目的是用一些字符串值(future.complete(getResult(input)))完成CompletableFuture,然后应用一些函数,你最好把thenApply()放在最后(你返回未来的地方)。

public CompletableFuture<String> getMyFuture(String input)
{
CompletableFuture<String> future = new CompletableFuture<String>();
ExecutorService service = Executors.newFixedThreadPool(6);
service.submit(() -> {
try {
future.complete(getResult(input));
} catch (InterruptedException e) {
e.printStackTrace();
}
});
return future.thenApply(result -> result+ "::");
}

我不知道如何用更易于理解的方式解释它。但简而言之:您在Runnable错误的对象引用上调用complete()方法

您正在创建两个CompletableFuture实例。第一个通过new CompletableFuture<String>()创建永远不会完成,你甚至没有保留对它的引用来使完成它成为可能。

第二个是通过在第一个函数上调用.thenApply((result) -> result+ "::")创建的,可以在第一个函数完成后通过计算指定的函数来完成,使用第一个函数的结果作为函数的参数。但是,由于第一个永远不会完成,因此该函数变得无关紧要。

但是CompletableFuture实例可以由任何人完成,而不仅仅是传递给链接方法的函数。完成的可能性甚至在其类名中突出显示。如果多次完成尝试,其中一个将是第一个,赢得比赛,所有后续完成尝试将被忽略。在您的代码中,您只有一次完成尝试,它将使用getResult返回的值成功完成它,而无需进行任何调整。

您可以更改代码以保留对第一个CompletableFuture实例的引用以手动complete它,以便使用传递给thenApply的函数完成第二个实例,但另一方面,这里不需要手动完成:

public CompletableFuture<String> getMyFuture(String input) {   
ExecutorService service = Executors.newFixedThreadPool(6);
return CompletableFuture.supplyAsync(() -> getResult(input), service)
.thenApply(result -> result + "::");
}
public String getResult(String input) {
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(3));
return "hello "+ input +" :" + LocalTime.now();
}    

当指定要supplyAsync的执行器时,将使用该执行器计算函数。不需要更多。

不用说,这只是一个例子。你永远不应该创建一个临时的线程池执行器,因为线程池执行器的全部意义在于允许重用线程(而你只使用这六个线程中的一个),并且它应该在使用后关闭。

相关内容

最新更新