这两个方法,都是选择最快执行完毕的CompletableFuture,然后再选择不同的处理方式接着处理.
CompletableFuture实现了CompletionStage接口,查看CompletionStage官方文档
CompletionStage定义了计算阶段的三个分类:功能,消费者或可运行(分别为apply ,accept或run)
具体取决于是否需要参数和/或生成结果。 例如:
stage.thenApply(x -> square(x))
.thenAccept(x -> System.out.print(x))
.thenRun(() -> System.out.println())
这两个方法,每个方法都有两个签名,一个带有线程池,一个不带线程池.
每个方法都有个函数式接口,apply相当于Function会有一个返回的类型,accept相当于consumer.
函数式接口在得到最快执行完毕的future后,会被执行
带有线程池的方法,为当前的任务指定了不同的线程池,从而隔离不同任务的执行线程,避免相互影响.
acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action, Executor executor)
acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action)
applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T,U> fn,Executor executor)
applyToEitherAsync(
CompletionStage<? extends T> other, Function<? super T,U> fn)
他们还有不是异步的版本,acceptEither和applyToEither.不是异步的版本以为着接下来的任务,会使用上个任务的线程继续执行接下来的任务
异步的CompletableFuture没有太好的办法去指定超时,利用acceptEitherAsync或acceptEither,可以限定一个超时时间,
时间到了,让另一个future返回异常完成,然后就不会再执行接下来的函数式接口了
public class test28 {
public static void main(String[] args) {
CompletableFuture<String> responseFuture = CompletableFuture.supplyAsync(() -> asyncCode());
CompletableFuture<String> oneSecondTimeout = failAfter(Duration.ofSeconds(1));
responseFuture
.acceptEither(oneSecondTimeout, a -> send(a))
.exceptionally(throwable -> {
System.out.println("异常:" + throwable);
return null;
});
}
public static <T> CompletableFuture<T> failAfter(Duration duration) {
CompletableFuture<T> promise = new CompletableFuture<>();
try {
Thread.sleep(duration.toMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
final TimeoutException ex = new TimeoutException("Timeout after " + duration);
promise.completeExceptionally(ex);
return promise;
}
public static String asyncCode() {
try {
System.out.println("asyncCode");
Thread.sleep(3000);
return "success";
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void send(String str) {
System.out.println("send a message:" + str);
}
}