我无法理解thenApply(
和之间的区别thenCompose()
.
那么,有人可以提供有效的用例吗?
来自Java文档:
thenApply(Function<? super T,? extends U> fn)
Run Code Online (Sandbox Code Playgroud)
返回一个新的
CompletionStage
,当该阶段正常完成时,将使用此阶段的结果作为所提供函数的参数执行.
thenCompose(Function<? super T,? extends CompletionStage<U>> fn)
Run Code Online (Sandbox Code Playgroud)
返回一个新的
CompletionStage
,当此阶段正常完成时,将使用此阶段作为所提供函数的参数执行.
我得到的第二个参数thenCompose
扩展了CompletionStage,thenApply
而不是.
有人可以提供一个例子,我必须使用thenApply
何时使用thenCompose
?
我想转换List<CompletableFuture<X>>
成CompletableFuture<List<T>>
.这非常有用,因为当您有许多异步任务并且需要获得所有异步任务的结果时.
如果其中任何一个失败,则最终的未来将失败.这就是我实施的方式:
public static <T> CompletableFuture<List<T>> sequence2(List<CompletableFuture<T>> com, ExecutorService exec) {
if(com.isEmpty()){
throw new IllegalArgumentException();
}
Stream<? extends CompletableFuture<T>> stream = com.stream();
CompletableFuture<List<T>> init = CompletableFuture.completedFuture(new ArrayList<T>());
return stream.reduce(init, (ls, fut) -> ls.thenComposeAsync(x -> fut.thenApplyAsync(y -> {
x.add(y);
return x;
},exec),exec), (a, b) -> a.thenCombineAsync(b,(ls1,ls2)-> {
ls1.addAll(ls2);
return ls1;
},exec));
}
Run Code Online (Sandbox Code Playgroud)
要运行它:
ExecutorService executorService = Executors.newCachedThreadPool();
Stream<CompletableFuture<Integer>> que = IntStream.range(0,100000).boxed().map(x -> CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep((long) (Math.random() * 10));
} catch (InterruptedException e) {
e.printStackTrace(); …
Run Code Online (Sandbox Code Playgroud) 我努力,但没有发现任何文章或博客清楚地比较ListenableFuture
和CompletableFuture
,并提供了一个很好的分析.
因此,如果有人能够解释或指向我这样的博客或文章,那对我来说真的很好.
我想写一个返回a的异步方法CompletableFuture
.未来的唯一目的是跟踪方法何时完成,而不是结果.返回CompletableFuture<Void>
还是更好CompletableFuture<?>
?有理由偏爱其中一个,还是可以互换?
CompletableFuture
本身CompletableFuture<Void>
从它的许多方法返回.java.nio
有一个Future<Void>
在AsynchronousSocketChannel
:Future<Void> connect(SocketAddress remote)
.java.util.concurrent
类ExecutorService
和ScheduledExecutorService
返回Future<?>
:例如,with Future<?> submit(Runnable task)
.请注意,我只询问返回类型,而不是参数列表,变量声明或其他上下文.
Java 8有一个函数CompletableFuture.allOf(CompletableFuture<?>...cfs)
,它返回一个CompletableFuture
在所有给定的期货完成时完成的函数.
但是,我几乎总是不处理一个CompletableFuture
s 数组,而是有一个List<CompletableFuture>
.当然,我可以使用这种toArray()
方法,但是这必须经常在数组和列表之间来回转换,这有点痛苦.
如果有一个光滑的方式来CompletableFuture<List<T>>
换取a List<CompletableFuture<T>>
,而不是经常不得不投入中间数组创建,那将是非常好的.有没有人知道在Java 8中这样做的方法?
假设我有以下代码:
CompletableFuture<Integer> future
= CompletableFuture.supplyAsync( () -> 0);
Run Code Online (Sandbox Code Playgroud)
thenApply
案件:
future.thenApply( x -> x + 1 )
.thenApply( x -> x + 1 )
.thenAccept( x -> System.out.println(x));
Run Code Online (Sandbox Code Playgroud)
这里输出为2.现在如下thenApplyAsync
:
future.thenApplyAsync( x -> x + 1 ) // first step
.thenApplyAsync( x -> x + 1 ) // second step
.thenAccept( x -> System.out.println(x)); // third step
Run Code Online (Sandbox Code Playgroud)
我在这个博客中读到,每个thenApplyAsync
都是在一个单独的线程中执行,并且"同时"(这意味着thenApplyAsyncs
在thenApplyAsyncs
完成之前开始跟随),如果是这样,如果第一步没有完成,第二步的输入参数值是多少?
如果不采取第二步,第一步的结果会在哪里?第三步将采取哪一步的结果?
如果第二步必须等待第一步的结果那么重点是Async
什么?
这里x - > x + 1只是为了表明这一点,我想知道的是在非常长的计算情况下.
我遇到过Java 8 CompletableFuture.exceptionally方法的奇怪行为.如果我执行此代码,它可以正常工作并打印java.lang.RuntimeException
CompletableFuture<String> future = new CompletableFuture<>();
future.completeExceptionally(new RuntimeException());
future.exceptionally(e -> {
System.out.println(e.getClass());
return null;
});
Run Code Online (Sandbox Code Playgroud)
但是如果我在将来的处理中添加另一个步骤,就像thenApply
异常类型更改为java.util.concurrent.CompletionException
包含在内部的原始异常.
CompletableFuture<String> future = new CompletableFuture<>();
future.completeExceptionally(new RuntimeException());
future.thenApply(v-> v).exceptionally(e -> {
System.out.println(e);
return null;
});
Run Code Online (Sandbox Code Playgroud)
有什么理由说这应该发生吗?在我看来,这是非常令人惊讶的.
要并行或异步运行一些东西我可以使用ExecutorService:<T> Future<T> submit(Runnable task, T result);
或CompletableFuture Api :( static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor);
假设我在两种情况下使用相同的Executor)
除了返回类型Future
与CompletableFuture
存在任何显着差异.或何时使用什么?
如果我使用CompletableFuture
默认的API Executor
(没有执行程序的方法)有什么区别?
我有以下代码:
// How to throw the ServerException?
public void myFunc() throws ServerException{
// Some code
CompletableFuture<A> a = CompletableFuture.supplyAsync(() -> {
try {
return someObj.someFunc();
} catch(ServerException ex) {
// throw ex; gives an error here.
}
}));
// Some code
}
Run Code Online (Sandbox Code Playgroud)
someFunc()
抛出一个ServerException
.我不想在这里处理这个问题,而是将异常抛给someFunc()
调用者myFunc()
.
我正在阅读文档CompletableFuture
和描述thenAccept()
是
返回一个新的CompletionStage,当此阶段正常完成时,将使用此阶段的结果作为所提供操作的参数执行.
而且thenApply()
是
返回一个新的CompletionStage,当这个阶段正常完成时,将执行此阶段的结果作为所提供函数的参数.``
谁能用一些简单的例子解释两者之间的区别?