CompletableFuture源码解读

介绍

CompletableFuture是Java编程语言中的一个类,它位于java.util.concurrent包下,从Java 8版本开始引入。CompletableFuture是一种用于处理异步操作和并发编程的工具,它提供了一种更灵活、更强大的方式来处理异步任务的完成、组合和转换。

在传统的Java中,我们通常使用Future来表示一个异步操作的结果,但Future存在一些限制,比如不能手动设置结果,不能直接进行操作结果的转换和组合等。而CompletableFuture则在这些方面提供了更多的功能。

以下是CompletableFuture的一些重要特性:

  1. 异步操作的创建和执行: 你可以使用CompletableFuture的工厂方法,比如supplyAsyncrunAsync,来创建并执行异步任务。这些方法可以接受一个Supplier(无参返回值)或Runnable(无返回值)作为任务,并返回一个CompletableFuture对象。
  2. 异步操作的组合: CompletableFuture支持多个异步操作的组合,可以通过一系列的方法链来实现。例如,你可以使用thenApplythenComposethenCombine等方法将一个异步操作的结果传递给下一个操作。
  3. 异常处理: CompletableFuture允许你通过exceptionallyhandle等方法来处理异步操作中抛出的异常。
  4. 合并多个异步操作: 你可以使用allOfanyOf等方法来合并多个CompletableFuture,并等待它们的全部或部分完成。
  5. 转换: CompletableFuture提供了许多方法来对异步操作的结果进行转换,比如thenApplythenAcceptthenRun等。
  6. 超时和完成: 你可以使用completecompleteExceptionallycompleteAsync等方法来手动设置CompletableFuture的结果或异常,也可以使用completeOnTimeout来在一定时间内完成操作,避免永久阻塞。
  7. 等待和阻塞: 你可以使用joinget等方法来等待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);
}

runAsyncsupplyAsync都有两种创建方法,带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

这个类是一个抽象类,实现了RunnableAsynchronousCompletionTask接口继承ForkJoinTask类,所以该类就是个Future,并且在该类中的volatile Completion nextCompletableFuture中有也有很多的进栈出栈的操作,由此可以得出CompletableFuture其实就相当于是一个链表,该Completion类有很多的实现类,例如BitAcceptBitApplyBitCompletionBitRelayUniCompletionUniAccept等等,挺多的。

这里就列举一个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();

}

该接口可以解读为:

异步计算的一个阶段,当一个阶段完成执行操作或者计算值后,当前阶段在执行或者计算终止时完成,但这可能反过来出发其他依赖的阶段,此接口中定义的功能仅采用了几种基本形式,这些形式可扩展到更大的方法集以捕获一系列使用风格:

阶段执行的计算可以表示为 FunctionConsumerRunnable(分别使用名称包括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相应命名的方法来组合它们的结果或效果(thenCombinethenCombineAsync)。由两个阶段之一触发的结果,我们不能使用combine去组合他们的结果,因为这个阶段无法确保这个结果是那个与之依赖的阶段返回的结果。
阶段之间的依赖关系控制计算的触发,但不保证任何特定的顺序

此外,新阶段计算的执行可以通过三种方式中的任何一种进行安排:默认执行默认异步执行(使用带有后缀async的方法,该方法采用阶段的默认异步执行工具)或自定义(通过提供的Executor 自定义)。默认和异步模式的执行属性由 CompletionStage 实现指定,而不是此接口指定。具有显式 Executor 参数的方法可能具有任意执行属性,甚至可能不支持并发执行,但会以适应异步的方式进行处理。

有两种方法形式支持处理触发阶段是否正常完成或异常完成:

方法**whenComplete**允许注入操作而不管结果如何,否则在完成时保留结果。方法handle还允许该阶段计算替换结果,该结果可以启用其他依赖阶段的进一步处理。在所有其他情况下,如果某个阶段的计算因(未经检查的)异常或错误而突然终止,则需要其完成的所有依赖阶段也会异常完成,并CompletionException将异常作为其原因。如果一个阶段依赖于两个阶段,并且两个阶段都异常完成,则 CompletionException 可能对应于这些异常之一。如果一个阶段依赖于另外两个阶段,并且只有其中一个阶段异常完成,则无法保证依赖阶段是正常完成还是异常完成。在方法whenComplete的情况下,当提供的操作本身遇到异常时,如果尚未异常完成,则阶段会异常完成并显示此异常。

所有方法都遵循上述触发、执行和异常完成规范(在各个方法规范中不再重复)。此外,虽然用于向接受它们的方法传递完成结果(即类型T的参数)的参数可能为 null,但为任何其他参数传递 null 值将导致抛出NullPointerException

该接口不定义初始创建、强制正常或异常完成、探测完成状态或结果、等待阶段完成的方法。 CompletionStage 的实现可以酌情提供实现此类效果的方法。方法toCompletableFuture通过提供通用转换类型来实现此接口的不同实现之间的互操作性。

小结:

这个接口的设计支持了链式的操作风格,你可以通过多次调用不同的方法来构建一个异步操作的流水线,从而实现更加复杂的异步操作组合。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贪吃的小松鼠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值