[英]thenApply in CompletableFuture
在下面的代码中
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();
}
我期望输出包含尾部的“ ::”,但程序不是“ hello first:16:49:30.231”我的apply实现正确吗?
您正在调用第一行获得的CompletionStage
complete()
方法(在此处称为“ 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
的函数来完成第二个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
,将使用该执行程序对函数进行评估。 不需要更多。
不用说,这只是举例。 您永远不应创建一个临时线程池执行程序,因为线程池执行程序的全部目的是允许重用线程(并且您仅使用这六个线程之一),并且在使用后应将其关闭。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.