介绍
CompletableFuture
是Java编程语言中的一个类,它位于java.util.concurrent
包下,从Java 8版本开始引入。CompletableFuture
是一种用于处理异步操作和并发编程的工具,它提供了一种更灵活、更强大的方式来处理异步任务的完成、组合和转换。
在传统的Java中,我们通常使用Future
来表示一个异步操作的结果,但Future
存在一些限制,比如不能手动设置结果,不能直接进行操作结果的转换和组合等。而CompletableFuture
则在这些方面提供了更多的功能。
以下是CompletableFuture
的一些重要特性:
- 异步操作的创建和执行: 你可以使用
CompletableFuture
的工厂方法,比如supplyAsync
和runAsync
,来创建并执行异步任务。这些方法可以接受一个Supplier
(无参返回值)或Runnable
(无返回值)作为任务,并返回一个CompletableFuture
对象。 - 异步操作的组合:
CompletableFuture
支持多个异步操作的组合,可以通过一系列的方法链来实现。例如,你可以使用thenApply
、thenCompose
、thenCombine
等方法将一个异步操作的结果传递给下一个操作。 - 异常处理:
CompletableFuture
允许你通过exceptionally
、handle
等方法来处理异步操作中抛出的异常。 - 合并多个异步操作: 你可以使用
allOf
、anyOf
等方法来合并多个CompletableFuture
,并等待它们的全部或部分完成。 - 转换:
CompletableFuture
提供了许多方法来对异步操作的结果进行转换,比如thenApply
、thenAccept
、thenRun
等。 - 超时和完成: 你可以使用
complete
、completeExceptionally
、completeAsync
等方法来手动设置CompletableFuture
的结果或异常,也可以使用completeOnTimeout
来在一定时间内完成操作,避免永久阻塞。 - 等待和阻塞: 你可以使用
join
、get
等方法来等待CompletableFuture
的完成,并获取其结果。但要注意,过度的等待和阻塞可能会降低异步操作的效益。
使用
创建异步任务
CompletableFuture
提供了很多创建的方法
//不带返回值的异步
public static CompletableFuture<Void> runAsync(Runnable runnable) {
return asyncRunStage(asyncPool, runnable);
}
public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor) {
return asyncRunStage(screenExecutor(executor), runnable);
}
//带返回值的异步
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
return asyncSupplyStage(asyncPool, supplier);
}
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor) {
return asyncSupplyStage(screenExecutor(executor), supplier);
}
像runAsync
和supplyAsync
都有两种创建方法,带Executor和不带Executor的,区别在于不带使用的默认线程池(ForkJoinPool.commonPool()
)的方法,
/**
* 默认执行器——ForkJoinPool.commonPool()
*/
private static final Executor asyncPool = useCommonPool ? ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
另一个使用的是自定义线程池的方法传入一个线程池
下面我们看下这两个的使用例子
/**
* @author xs
*/
public class Main {
public static void main(String[] args) {
try {
//定义线程池
ExecutorService executorService = Executors.newSingleThreadExecutor();
System.out.println(Thread.currentThread().getName());
// 创建一个异步不带返回值的操作
CompletableFuture<Void> future1 = CompletableFuture.runAsync(
() -> System.out.println("hello CompletableFuture runAsync!" + Thread.currentThread().getName()),
executorService);
System.out.println("runAsync已经完成!" + future1.get());
// 创建一个异步带返回值的操作
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(
() -> "hello CompletableFuture supplyAsync!" + Thread.currentThread().getName(),executorService);
// 添加一个回调,当异步操作完成时输出结果
System.out.println(Thread.currentThread().getName());
System.out.println("supplyAsync已经完成!" + future2.get());
executorService.shutdown();
} catch (Exception e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
运行结果
main
hello CompletableFuture runAsync!pool-1-thread-1
runAsync已经完成!null
main
supplyAsync已经完成!hello CompletableFuture supplyAsync!pool-1-thread-1
从当前结果可以看到get方法会等待当前任务完成,会阻塞当前线程一直到任务完成,
/**
* 等待此 future 完成,然后返回其结果。
* 异常:
* CancellationException – 如果这个 future 被取消
* ExecutionException – 如果这个 future 异常完成
* InterruptedException – 如果当前线程在等待时被中断
*/
public T get() throws InterruptedException, ExecutionException {
Object r;
return reportGet((r = result) == null ? waitingGet(true) : r);
}
从输出的结果来看,不管事runAsync
还是supplyAsync
都是异步线程执行的,并且runAsync
是无返回值的get只能获取到null
获取结果的方式
/**
* 等待此 future 完成,然后返回其结果
* 异常:
* CancellationException – 如果这个 future 被取消
* ExecutionException – 如果这个 future 异常完成
* InterruptedException – 如果当前线程在等待时被中断
*/
public T get() throws InterruptedException, ExecutionException
/**
* 最多等待该 future 完成的给定时间,然后返回其结果
* 参数:timeout - 等待最长时间
* unit - 超市参数的时间单位
* 异常:
* CancellationException – 如果这个 future 被取消
* ExecutionException – 如果这个 future 异常完成
* InterruptedException – 如果当前线程在等待时被中断
*/
public T get(long timeout, TimeUnit unit)
/**
* 完成时返回结果值,如果异常完成则抛出(未经检查的)异常。为了更好地符合常见函数形式的使用,如果完成此 CompletableFuture 所涉及的计算抛出异常,则此方法
* 将抛出一个(未经检查的) CompletionException ,并将底层异常作为其原因
* 异常:
* CancellationException – 如果计算被取消
* CompletionException – 如果此 future 异常完成或完成计算引发异常
*/
public T join()
/**
* 完成时返回结果值
* 如果完成,则返回给定值IfAbsent
* @param valueIfAbsent 如果未完成时返回的值
* @return 结果值,如果完成,否则返回给定值IfAbsent
* 如果计算被取消则@抛出CancellationException
* 如果这个 future 完成了,则抛出 CompletionException
* 异常或完成计算抛出异常
*/
public T getNow(T valueIfAbsent)
/**
* 如果尚未完成,则将get()和相关方法返回的值设置为给定值value
* @param value 结果值
* @return 如果完成则为true,反之为false
*/
public boolean complete(T value)
/**
*如果尚未完成,则导致调用get()和相关方法抛出给定的异常ex
* @param ex 异常
* @return 如果完成则为true,反之为false
*/
public boolean completeExceptionally(Throwable ex) {
源码分析
runAsync()
的源码
public static CompletableFuture<Void> runAsync(Runnable runnable) {
return asyncRunStage(asyncPool, runnable);
}
public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor) {
return asyncRunStage(screenExecutor(executor), runnable);
}
这里的asyncPool
是一个静态成员变量
private static final Executor asyncPool = useCommonPool ? ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
private static final boolean useCommonPool = (ForkJoinPool.getCommonPoolParallelism() > 1);//获取公共池的并行度
然后就是asyncRunStage
static CompletableFuture<Void> asyncRunStage(Executor e, Runnable f) {
if (f == null) throw new NullPointerException();//如果Runnable为空直接抛出错误
CompletableFuture<Void> d = new CompletableFuture<Void>();
e.execute(new AsyncRun(d, f));//用来执行任务
return d;
}
其中的AsyncRun
类是实现了Runnable类的,看AsyncRun
源码
static final class AsyncRun extends ForkJoinTask<Void>
implements Runnable, AsynchronousCompletionTask {//实现了Runnable
CompletableFuture<Void> dep; Runnable fn;
AsyncRun(CompletableFuture<Void> dep, Runnable fn) {
this.dep = dep; this.fn = fn;
}
public final Void getRawResult() { return null; }
public final void setRawResult(Void v) {}
public final boolean exec() { run(); return true; }
public void run() {//主要方法 内部的run方法
CompletableFuture<Void> d; Runnable f; //局部变量用来提高性能
if ((d = dep) != null && (f = fn) != null) {//赋值判空
dep = null; fn = null;
if (d.result == null) {
try {
f.run();//执行
d.completeNull();//调用UNSAFE类的compareAndSwapObject()方法,以CAS的方法对CompletableFuture的结果赋值为null
// final boolean completeNull() {return UNSAFE.compareAndSwapObject(this, RESULT, null,NIL);
} catch (Throwable ex) {
d.completeThrowable(ex);
}
}
d.postComplete();//完成任务
}
}
}
其中的postComplete
我们后面和supplyAsync
一起讲
supplyAsync()
源码
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
return asyncSupplyStage(asyncPool, supplier);
}
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor) {
return asyncSupplyStage(screenExecutor(executor), supplier);
}
内部也是两个只有两个重构方法,返回调用的asyncSupplyStage()
这个方法,他的内部同asyncRunStage
是一样的不过执行内部传入的是一个AsyncSupply()
类
static <U> CompletableFuture<U> asyncSupplyStage(Executor e,
Supplier<U> f) {
if (f == null) throw new NullPointerException();
CompletableFuture<U> d = new CompletableFuture<U>();
e.execute(new AsyncSupply<U>(d, f));
return d;
}
static final class AsyncSupply<T> extends ForkJoinTask<Void>
implements Runnable, AsynchronousCompletionTask {
CompletableFuture<T> dep; Supplier<T> fn;
AsyncSupply(CompletableFuture<T> dep, Supplier<T> fn) {//构造
this.dep = dep; this.fn = fn;
}
public final Void getRawResult() { return null; }
public final void setRawResult(Void v) {}
public final boolean exec() { run(); return true; }
public void run() {
CompletableFuture<T> d; Supplier<T> f;
if ((d = dep) != null && (f = fn) != null) {
dep = null; fn = null;//dep 和 fn 的引用会被设置为 null,以防止重复执行。
if (d.result == null) {//防止重复执行,result不为空说明已经被设置,就不执行下面的操作了
try {
d.completeValue(f.get());
} catch (Throwable ex) {
d.completeThrowable(ex);
}
}
d.postComplete();//异步操作已完成,触发后续可能的回调和操作。
}
}
}
如果 f.get()
成功获取结果,通过 dep.completeValue() 方法将结果设置到 dep(CompletableFuture)中。completeValue()
方法调用UNSAFE的compareAndSwapObject()
为结果赋于指定的值,使用trycatch
包裹如果出现异常在内部捕获,方法会将异常设置到 dep
中
关键方法解读
postComplete()
分析
用于触发异步操作的完成,并处理依赖于该操作的其他操作或回调。该方法的作用是执行依赖项的回调和操作,确保整个异步操作流程能够顺利完成。
final void postComplete() {
/*
* On each step, variable f holds current dependents to pop
* and run. It is extended along only one path at a time,
* pushing others to avoid unbounded recursion.
*/
CompletableFuture<?> f = this; Completion h;
while ((h = f.stack) != null || (f != this && (h = (f = this).stack) != null)) {//判断stack栈是否为空
CompletableFuture<?> d; Completion t;
if (f.casStack(h, t = h.next)) {//在循环内部,尝试使用 CAS(比较并交换)操作将当前回调 h 从 f 的 stack 中移除,并将 h.next 赋给变量 t。
if (t != null) {//出栈的h不是最后一个元素,如果是最后一个元素直接最后一步
if (f != this) {//如果 f 不是当前实例,说明在循环执行期间 f 被修改了,那么将回调 h 推回 f 的 stack 中,继续下一轮循环。
pushStack(h);
continue;
}
h.next = null; // detach
}
//如果 t 为 null,说明已经没有其他回调等待执行了,将回调 h 的下一个回调引用设置为 null,将 h 从链表中分离
//尝试通过 tryFire(NESTED) 方法触发回调 h。如果触发成功,将触发后返回的新 CompletableFuture 实例存储在 d 中,然后将 f 更新为 d。如果触发失败,将 f 更新为当前实例。
f = (d = h.tryFire(NESTED)) == null ? this : d;
}
}
}
该方法主要就是在任务完成后,继续调用其他的依赖任务。
Completion
类分析
abstract static class Completion extends ForkJoinTask<Void>
implements Runnable, AsynchronousCompletionTask {
volatile Completion next; // Treiber stack link
/**
* Performs completion action if triggered, returning a
* dependent that may need propagation, if one exists.
*
* @param mode SYNC, ASYNC, or NESTED
*/
abstract CompletableFuture<?> tryFire(int mode);
/** Returns true if possibly still triggerable. Used by cleanStack. */
abstract boolean isLive();
public final void run() { tryFire(ASYNC); }
public final boolean exec() { tryFire(ASYNC); return true; }
public final Void getRawResult() { return null; }
public final void setRawResult(Void v) {}
}
public abstract class ForkJoinTask<V> implements Future<V>, Serializable {...}//ForkJoinTask实现了Future
这个类是一个抽象类,实现了Runnable
,AsynchronousCompletionTask
接口继承ForkJoinTask
类,所以该类就是个Future
,并且在该类中的volatile Completion next
和CompletableFuture
中有也有很多的进栈出栈的操作,由此可以得出CompletableFuture
其实就相当于是一个链表,该Completion
类有很多的实现类,例如BitAccept
、BitApply
、BitCompletion
、BitRelay
、UniCompletion
、UniAccept
等等,挺多的。
这里就列举一个UniCompletion
类
abstract static class UniCompletion<T,V> extends Completion {
Executor executor; // executor to use (null if none)
CompletableFuture<V> dep; // 表示依赖的 CompletableFuture,即在依赖完成时执行该完成处理。
CompletableFuture<T> src; // 表示源 CompletableFuture,即这个完成处理的触发与源 CompletableFuture 的完成相关。
UniCompletion(Executor executor, CompletableFuture<V> dep,CompletableFuture<T> src) {
this.executor = executor; this.dep = dep; this.src = src;
}
/**
* 这个方法用于尝试声明执行完成处理的权利。这是一个关键的方法,用于确保只有一个线程可以执行这个完成处理。通过compareAndSetForkJoinTaskTag方法比较并 * 交换 ForkJoinTask 的标签位来实现。如果成功获取了执行权,它会根据是否提供了 Executor 来决定是否执行完成处理。
*/
final boolean claim() {
Executor e = executor;
if (compareAndSetForkJoinTaskTag((short)0, (short)1)) {
if (e == null)
return true;
executor = null; // disable
e.execute(this);
}
return false;
}
/**
*这个方法用于判断完成处理是否仍然有效,即它是否还能被触发。如果 dep 不为 null,则认为这个完成处理仍然有效。
*/
final boolean isLive() { return dep != null; }
}
CompletionStage
接口源码分析
public interface CompletionStage<T> {
/**
* Returns a new CompletionStage that, when this stage completes
* normally, is executed with this stage's result as the argument
* to the supplied function.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param fn the function to use to compute the value of
* the returned CompletionStage
* @param <U> the function's return type
* @return the new CompletionStage
*/
public <U> CompletionStage<U> thenApply(Function<? super T,? extends U> fn);
/**
* Returns a new CompletionStage that, when this stage completes
* normally, is executed using this stage's default asynchronous
* execution facility, with this stage's result as the argument to
* the supplied function.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param fn the function to use to compute the value of
* the returned CompletionStage
* @param <U> the function's return type
* @return the new CompletionStage
*/
public <U> CompletionStage<U> thenApplyAsync
(Function<? super T,? extends U> fn);
/**
* Returns a new CompletionStage that, when this stage completes
* normally, is executed using the supplied Executor, with this
* stage's result as the argument to the supplied function.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param fn the function to use to compute the value of
* the returned CompletionStage
* @param executor the executor to use for asynchronous execution
* @param <U> the function's return type
* @return the new CompletionStage
*/
public <U> CompletionStage<U> thenApplyAsync
(Function<? super T,? extends U> fn,
Executor executor);
/**
* Returns a new CompletionStage that, when this stage completes
* normally, is executed with this stage's result as the argument
* to the supplied action.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param action the action to perform before completing the
* returned CompletionStage
* @return the new CompletionStage
*/
public CompletionStage<Void> thenAccept(Consumer<? super T> action);
/**
* Returns a new CompletionStage that, when this stage completes
* normally, is executed using this stage's default asynchronous
* execution facility, with this stage's result as the argument to
* the supplied action.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param action the action to perform before completing the
* returned CompletionStage
* @return the new CompletionStage
*/
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action);
/**
* Returns a new CompletionStage that, when this stage completes
* normally, is executed using the supplied Executor, with this
* stage's result as the argument to the supplied action.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param action the action to perform before completing the
* returned CompletionStage
* @param executor the executor to use for asynchronous execution
* @return the new CompletionStage
*/
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action,
Executor executor);
/**
* Returns a new CompletionStage that, when this stage completes
* normally, executes the given action.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param action the action to perform before completing the
* returned CompletionStage
* @return the new CompletionStage
*/
public CompletionStage<Void> thenRun(Runnable action);
/**
* Returns a new CompletionStage that, when this stage completes
* normally, executes the given action using this stage's default
* asynchronous execution facility.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param action the action to perform before completing the
* returned CompletionStage
* @return the new CompletionStage
*/
public CompletionStage<Void> thenRunAsync(Runnable action);
/**
* Returns a new CompletionStage that, when this stage completes
* normally, executes the given action using the supplied Executor.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param action the action to perform before completing the
* returned CompletionStage
* @param executor the executor to use for asynchronous execution
* @return the new CompletionStage
*/
public CompletionStage<Void> thenRunAsync(Runnable action,
Executor executor);
/**
* Returns a new CompletionStage that, when this and the other
* given stage both complete normally, is executed with the two
* results as arguments to the supplied function.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param other the other CompletionStage
* @param fn the function to use to compute the value of
* the returned CompletionStage
* @param <U> the type of the other CompletionStage's result
* @param <V> the function's return type
* @return the new CompletionStage
*/
public <U,V> CompletionStage<V> thenCombine
(CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn);
/**
* Returns a new CompletionStage that, when this and the other
* given stage complete normally, is executed using this stage's
* default asynchronous execution facility, with the two results
* as arguments to the supplied function.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param other the other CompletionStage
* @param fn the function to use to compute the value of
* the returned CompletionStage
* @param <U> the type of the other CompletionStage's result
* @param <V> the function's return type
* @return the new CompletionStage
*/
public <U,V> CompletionStage<V> thenCombineAsync
(CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn);
/**
* Returns a new CompletionStage that, when this and the other
* given stage complete normally, is executed using the supplied
* executor, with the two results as arguments to the supplied
* function.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param other the other CompletionStage
* @param fn the function to use to compute the value of
* the returned CompletionStage
* @param executor the executor to use for asynchronous execution
* @param <U> the type of the other CompletionStage's result
* @param <V> the function's return type
* @return the new CompletionStage
*/
public <U,V> CompletionStage<V> thenCombineAsync
(CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn,
Executor executor);
/**
* Returns a new CompletionStage that, when this and the other
* given stage both complete normally, is executed with the two
* results as arguments to the supplied action.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param other the other CompletionStage
* @param action the action to perform before completing the
* returned CompletionStage
* @param <U> the type of the other CompletionStage's result
* @return the new CompletionStage
*/
public <U> CompletionStage<Void> thenAcceptBoth
(CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action);
/**
* Returns a new CompletionStage that, when this and the other
* given stage complete normally, is executed using this stage's
* default asynchronous execution facility, with the two results
* as arguments to the supplied action.
*
* @param other the other CompletionStage
* @param action the action to perform before completing the
* returned CompletionStage
* @param <U> the type of the other CompletionStage's result
* @return the new CompletionStage
*/
public <U> CompletionStage<Void> thenAcceptBothAsync
(CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action);
/**
* Returns a new CompletionStage that, when this and the other
* given stage complete normally, is executed using the supplied
* executor, with the two results as arguments to the supplied
* function.
*
* @param other the other CompletionStage
* @param action the action to perform before completing the
* returned CompletionStage
* @param executor the executor to use for asynchronous execution
* @param <U> the type of the other CompletionStage's result
* @return the new CompletionStage
*/
public <U> CompletionStage<Void> thenAcceptBothAsync
(CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action,
Executor executor);
/**
* Returns a new CompletionStage that, when this and the other
* given stage both complete normally, executes the given action.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param other the other CompletionStage
* @param action the action to perform before completing the
* returned CompletionStage
* @return the new CompletionStage
*/
public CompletionStage<Void> runAfterBoth(CompletionStage<?> other,
Runnable action);
/**
* Returns a new CompletionStage that, when this and the other
* given stage complete normally, executes the given action using
* this stage's default asynchronous execution facility.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param other the other CompletionStage
* @param action the action to perform before completing the
* returned CompletionStage
* @return the new CompletionStage
*/
public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,
Runnable action);
/**
* Returns a new CompletionStage that, when this and the other
* given stage complete normally, executes the given action using
* the supplied executor.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param other the other CompletionStage
* @param action the action to perform before completing the
* returned CompletionStage
* @param executor the executor to use for asynchronous execution
* @return the new CompletionStage
*/
public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,
Runnable action,
Executor executor);
/**
* Returns a new CompletionStage that, when either this or the
* other given stage complete normally, is executed with the
* corresponding result as argument to the supplied function.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param other the other CompletionStage
* @param fn the function to use to compute the value of
* the returned CompletionStage
* @param <U> the function's return type
* @return the new CompletionStage
*/
public <U> CompletionStage<U> applyToEither
(CompletionStage<? extends T> other,
Function<? super T, U> fn);
/**
* Returns a new CompletionStage that, when either this or the
* other given stage complete normally, is executed using this
* stage's default asynchronous execution facility, with the
* corresponding result as argument to the supplied function.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param other the other CompletionStage
* @param fn the function to use to compute the value of
* the returned CompletionStage
* @param <U> the function's return type
* @return the new CompletionStage
*/
public <U> CompletionStage<U> applyToEitherAsync
(CompletionStage<? extends T> other,
Function<? super T, U> fn);
/**
* Returns a new CompletionStage that, when either this or the
* other given stage complete normally, is executed using the
* supplied executor, with the corresponding result as argument to
* the supplied function.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param other the other CompletionStage
* @param fn the function to use to compute the value of
* the returned CompletionStage
* @param executor the executor to use for asynchronous execution
* @param <U> the function's return type
* @return the new CompletionStage
*/
public <U> CompletionStage<U> applyToEitherAsync
(CompletionStage<? extends T> other,
Function<? super T, U> fn,
Executor executor);
/**
* Returns a new CompletionStage that, when either this or the
* other given stage complete normally, is executed with the
* corresponding result as argument to the supplied action.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param other the other CompletionStage
* @param action the action to perform before completing the
* returned CompletionStage
* @return the new CompletionStage
*/
public CompletionStage<Void> acceptEither
(CompletionStage<? extends T> other,
Consumer<? super T> action);
/**
* Returns a new CompletionStage that, when either this or the
* other given stage complete normally, is executed using this
* stage's default asynchronous execution facility, with the
* corresponding result as argument to the supplied action.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param other the other CompletionStage
* @param action the action to perform before completing the
* returned CompletionStage
* @return the new CompletionStage
*/
public CompletionStage<Void> acceptEitherAsync
(CompletionStage<? extends T> other,
Consumer<? super T> action);
/**
* Returns a new CompletionStage that, when either this or the
* other given stage complete normally, is executed using the
* supplied executor, with the corresponding result as argument to
* the supplied function.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param other the other CompletionStage
* @param action the action to perform before completing the
* returned CompletionStage
* @param executor the executor to use for asynchronous execution
* @return the new CompletionStage
*/
public CompletionStage<Void> acceptEitherAsync
(CompletionStage<? extends T> other,
Consumer<? super T> action,
Executor executor);
/**
* Returns a new CompletionStage that, when either this or the
* other given stage complete normally, executes the given action.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param other the other CompletionStage
* @param action the action to perform before completing the
* returned CompletionStage
* @return the new CompletionStage
*/
public CompletionStage<Void> runAfterEither(CompletionStage<?> other,
Runnable action);
/**
* Returns a new CompletionStage that, when either this or the
* other given stage complete normally, executes the given action
* using this stage's default asynchronous execution facility.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param other the other CompletionStage
* @param action the action to perform before completing the
* returned CompletionStage
* @return the new CompletionStage
*/
public CompletionStage<Void> runAfterEitherAsync
(CompletionStage<?> other,
Runnable action);
/**
* Returns a new CompletionStage that, when either this or the
* other given stage complete normally, executes the given action
* using the supplied executor.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param other the other CompletionStage
* @param action the action to perform before completing the
* returned CompletionStage
* @param executor the executor to use for asynchronous execution
* @return the new CompletionStage
*/
public CompletionStage<Void> runAfterEitherAsync
(CompletionStage<?> other,
Runnable action,
Executor executor);
/**
* Returns a new CompletionStage that, when this stage completes
* normally, is executed with this stage as the argument
* to the supplied function.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param fn the function returning a new CompletionStage
* @param <U> the type of the returned CompletionStage's result
* @return the CompletionStage
*/
public <U> CompletionStage<U> thenCompose
(Function<? super T, ? extends CompletionStage<U>> fn);
/**
* Returns a new CompletionStage that, when this stage completes
* normally, is executed using this stage's default asynchronous
* execution facility, with this stage as the argument to the
* supplied function.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param fn the function returning a new CompletionStage
* @param <U> the type of the returned CompletionStage's result
* @return the CompletionStage
*/
public <U> CompletionStage<U> thenComposeAsync
(Function<? super T, ? extends CompletionStage<U>> fn);
/**
* Returns a new CompletionStage that, when this stage completes
* normally, is executed using the supplied Executor, with this
* stage's result as the argument to the supplied function.
*
* See the {@link CompletionStage} documentation for rules
* covering exceptional completion.
*
* @param fn the function returning a new CompletionStage
* @param executor the executor to use for asynchronous execution
* @param <U> the type of the returned CompletionStage's result
* @return the CompletionStage
*/
public <U> CompletionStage<U> thenComposeAsync
(Function<? super T, ? extends CompletionStage<U>> fn,
Executor executor);
/**
* Returns a new CompletionStage that, when this stage completes
* exceptionally, is executed with this stage's exception as the
* argument to the supplied function. Otherwise, if this stage
* completes normally, then the returned stage also completes
* normally with the same value.
*
* @param fn the function to use to compute the value of the
* returned CompletionStage if this CompletionStage completed
* exceptionally
* @return the new CompletionStage
*/
public CompletionStage<T> exceptionally
(Function<Throwable, ? extends T> fn);
/**
* Returns a new CompletionStage with the same result or exception as
* this stage, that executes the given action when this stage completes.
*
* <p>When this stage is complete, the given action is invoked with the
* result (or {@code null} if none) and the exception (or {@code null}
* if none) of this stage as arguments. The returned stage is completed
* when the action returns. If the supplied action itself encounters an
* exception, then the returned stage exceptionally completes with this
* exception unless this stage also completed exceptionally.
*
* @param action the action to perform
* @return the new CompletionStage
*/
public CompletionStage<T> whenComplete
(BiConsumer<? super T, ? super Throwable> action);
/**
* Returns a new CompletionStage with the same result or exception as
* this stage, that executes the given action using this stage's
* default asynchronous execution facility when this stage completes.
*
* <p>When this stage is complete, the given action is invoked with the
* result (or {@code null} if none) and the exception (or {@code null}
* if none) of this stage as arguments. The returned stage is completed
* when the action returns. If the supplied action itself encounters an
* exception, then the returned stage exceptionally completes with this
* exception unless this stage also completed exceptionally.
*
* @param action the action to perform
* @return the new CompletionStage
*/
public CompletionStage<T> whenCompleteAsync
(BiConsumer<? super T, ? super Throwable> action);
/**
* Returns a new CompletionStage with the same result or exception as
* this stage, that executes the given action using the supplied
* Executor when this stage completes.
*
* <p>When this stage is complete, the given action is invoked with the
* result (or {@code null} if none) and the exception (or {@code null}
* if none) of this stage as arguments. The returned stage is completed
* when the action returns. If the supplied action itself encounters an
* exception, then the returned stage exceptionally completes with this
* exception unless this stage also completed exceptionally.
*
* @param action the action to perform
* @param executor the executor to use for asynchronous execution
* @return the new CompletionStage
*/
public CompletionStage<T> whenCompleteAsync
(BiConsumer<? super T, ? super Throwable> action,
Executor executor);
/**
* Returns a new CompletionStage that, when this stage completes
* either normally or exceptionally, is executed with this stage's
* result and exception as arguments to the supplied function.
*
* <p>When this stage is complete, the given function is invoked
* with the result (or {@code null} if none) and the exception (or
* {@code null} if none) of this stage as arguments, and the
* function's result is used to complete the returned stage.
*
* @param fn the function to use to compute the value of the
* returned CompletionStage
* @param <U> the function's return type
* @return the new CompletionStage
*/
public <U> CompletionStage<U> handle
(BiFunction<? super T, Throwable, ? extends U> fn);
/**
* Returns a new CompletionStage that, when this stage completes
* either normally or exceptionally, is executed using this stage's
* default asynchronous execution facility, with this stage's
* result and exception as arguments to the supplied function.
*
* <p>When this stage is complete, the given function is invoked
* with the result (or {@code null} if none) and the exception (or
* {@code null} if none) of this stage as arguments, and the
* function's result is used to complete the returned stage.
*
* @param fn the function to use to compute the value of the
* returned CompletionStage
* @param <U> the function's return type
* @return the new CompletionStage
*/
public <U> CompletionStage<U> handleAsync
(BiFunction<? super T, Throwable, ? extends U> fn);
/**
* Returns a new CompletionStage that, when this stage completes
* either normally or exceptionally, is executed using the
* supplied executor, with this stage's result and exception as
* arguments to the supplied function.
*
* <p>When this stage is complete, the given function is invoked
* with the result (or {@code null} if none) and the exception (or
* {@code null} if none) of this stage as arguments, and the
* function's result is used to complete the returned stage.
*
* @param fn the function to use to compute the value of the
* returned CompletionStage
* @param executor the executor to use for asynchronous execution
* @param <U> the function's return type
* @return the new CompletionStage
*/
public <U> CompletionStage<U> handleAsync
(BiFunction<? super T, Throwable, ? extends U> fn,
Executor executor);
/**
* Returns a {@link CompletableFuture} maintaining the same
* completion properties as this stage. If this stage is already a
* CompletableFuture, this method may return this stage itself.
* Otherwise, invocation of this method may be equivalent in
* effect to {@code thenApply(x -> x)}, but returning an instance
* of type {@code CompletableFuture}. A CompletionStage
* implementation that does not choose to interoperate with others
* may throw {@code UnsupportedOperationException}.
*
* @return the CompletableFuture
* @throws UnsupportedOperationException if this implementation
* does not interoperate with CompletableFuture
*/
public CompletableFuture<T> toCompletableFuture();
}
该接口可以解读为:
异步计算的一个阶段,当一个阶段完成执行操作或者计算值后,当前阶段在执行或者计算终止时完成,但这可能反过来出发其他依赖的阶段,此接口中定义的功能仅采用了几种基本形式,这些形式可扩展到更大的方法集以捕获一系列使用风格:
阶段执行的计算可以表示为 Function
、Consumer
或 Runnable
(分别使用名称包括apply accept或run 的方法),具体取决于它是否需要参数或生成结果。例如,
stage.thenApply(x -> square(x)).thenAccept(x -> System.out.print(x)).thenRun(() -> System.out.println())
在上面这个例子中x -> square(x)
就是一个Function类的阶段他返回了一个x的值到下一个Comsumer
类的拼接阶段x -> System.out.print(x)
。最后这个System.out.println()
是Runnable
的一个阶段,他会消耗结果也不会返回值。
一个、两个或者任意一个阶段的完成都会触发依赖的CompletionStage
的执行。使用带有前缀then的方法来安排单个阶段的依赖关系。通过完成两个阶段而触发的那些可以使用combine相应命名的方法来组合它们的结果或效果(thenCombine
、thenCombineAsync
)。由两个阶段之一触发的结果,我们不能使用combine去组合他们的结果,因为这个阶段无法确保这个结果是那个与之依赖的阶段返回的结果。
阶段之间的依赖关系控制计算的触发,但不保证任何特定的顺序。
此外,新阶段计算的执行可以通过三种方式中的任何一种进行安排:默认执行、默认异步执行(使用带有后缀async
的方法,该方法采用阶段的默认异步执行工具)或自定义(通过提供的Executor 自定义)。默认和异步模式的执行属性由 CompletionStage
实现指定,而不是此接口指定。具有显式 Executor 参数的方法可能具有任意执行属性,甚至可能不支持并发执行,但会以适应异步的方式进行处理。
有两种方法形式支持处理触发阶段是否正常完成或异常完成:
方法**whenComplete**
允许注入操作而不管结果如何,否则在完成时保留结果。方法handle还允许该阶段计算替换结果,该结果可以启用其他依赖阶段的进一步处理。在所有其他情况下,如果某个阶段的计算因(未经检查的)异常或错误而突然终止,则需要其完成的所有依赖阶段也会异常完成,并CompletionException
将异常作为其原因。如果一个阶段依赖于两个阶段,并且两个阶段都异常完成,则 CompletionException
可能对应于这些异常之一。如果一个阶段依赖于另外两个阶段,并且只有其中一个阶段异常完成,则无法保证依赖阶段是正常完成还是异常完成。在方法whenComplete
的情况下,当提供的操作本身遇到异常时,如果尚未异常完成,则阶段会异常完成并显示此异常。
所有方法都遵循上述触发、执行和异常完成规范(在各个方法规范中不再重复)。此外,虽然用于向接受它们的方法传递完成结果(即类型T的参数)的参数可能为 null,但为任何其他参数传递 null 值将导致抛出NullPointerException
。
该接口不定义初始创建、强制正常或异常完成、探测完成状态或结果、等待阶段完成的方法。 CompletionStage
的实现可以酌情提供实现此类效果的方法。方法toCompletableFuture
通过提供通用转换类型来实现此接口的不同实现之间的互操作性。
小结:
这个接口的设计支持了链式的操作风格,你可以通过多次调用不同的方法来构建一个异步操作的流水线,从而实现更加复杂的异步操作组合。