[英]thenApply in CompletableFuture
In the following code 在下面的代码中
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();
}
I am expecting the output to contain trailing "::" but program doesn't is "hello first :16:49:30.231 " Is my implementation of apply correct ? 我期望输出包含尾部的“ ::”,但程序不是“ hello first:16:49:30.231”我的apply实现正确吗?
You're invoking complete()
method of the CompletionStage
that you got at the first line (where you call "thenApply" method). 您正在调用第一行获得的
CompletionStage
complete()
方法(在此处称为“ thenApply”方法)。
If your intention is to complete the CompletableFuture
with some string value ( future.complete(getResult(input))
) and then apply some function, you'd better place thenApply()
at the end (where you return the future). 如果您打算用某个字符串值(
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+ "::");
}
I don't know how to explain it in a more understandable way. 我不知道如何以更容易理解的方式解释它。 But in short: you're calling
complete()
method on the wrong object reference inside your Runnable
. 但简而言之: 您正在对
Runnable
错误的对象引用调用complete()
方法 。
You are creating two CompletableFuture
instances. 您正在创建两个
CompletableFuture
实例。 The first, created via new CompletableFuture<String>()
will never get completed, you don't even keep a reference to it that would make completing it possible. 第一个是通过
new CompletableFuture<String>()
创建的,它将永远不会完成,您甚至不会保留对其进行引用的引用,从而无法完成。
The second, created by calling .thenApply((result) -> result+ "::")
on the first one, could get completed by evaluating the specified function once the first one completed, using the first's result as an argument to the function. 通过在第一个函数上调用
.thenApply((result) -> result+ "::")
创建的第二个函数,可以在第一个函数完成后通过评估指定的函数来完成,并使用第一个函数的结果作为函数的参数。 However, since the first never completes, the function becomes irrelevant. 但是,由于第一个永远不会完成,因此该功能变得无关紧要。
But CompletableFuture
instances can get completed by anyone, not just a function passed to a chaining method. 但是
CompletableFuture
实例可以由任何人完成,而不仅仅是传递给链接方法的函数。 The possibility to get completed is even prominently displayed in its class name. 完成的可能性甚至在班级名称中突出显示。 In case of multiple completion attempts, one would turn out to be the first one, winning the race and all subsequent completion attempts will be ignored.
如果进行了多次完成尝试,那么结果将是第一个赢得比赛,并且所有后续完成尝试都将被忽略。 In your code, you have only one completion attempt, which will successfully complete it with the value returned by
getResult
, without any adaptations. 在您的代码中,您只有一次完成尝试,它将使用
getResult
返回的值成功完成它,而无需进行任何修改。
You could change your code to keep a reference to the first CompletableFuture
instance to complete
it manually, so that the second gets completed using the function passed to thenApply
, but on the other hand, there is no need for manual completion here: 您可以更改代码以保留对第一个
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();
}
When specifying the executor to supplyAsync
, the function will be evaluated using that executor. 将执行程序指定为
supplyAsync
,将使用该执行程序对函数进行评估。 More is not needed. 不需要更多。
Needless to say, that's just for example. 不用说,这只是举例。 You should never create a temporary thread pool executor, as the whole point of a thread pool executor is to allow reusing the threads (and you're using only one of these six threads at all) and it should get shut down after use.
您永远不应创建一个临时线程池执行程序,因为线程池执行程序的全部目的是允许重用线程(并且您仅使用这六个线程之一),并且在使用后应将其关闭。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.