CompletableFuture函数原理

CompletableFuture是Future接口的扩展和增强。CompletableFuture实现了Future接口,并在此基础上进行了丰富地扩展,完美地弥补了Future上述的种种问题。更为重要的是,CompletableFuture实现了对任务的编排能力。借助这项能力,我们可以轻松地组织不同任务的运行顺序、规则以及方式。

运用:

kotlin 复制代码
public class CompletableFutureHandle {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("发生异常");
//            throw new RuntimeException("我是异常..");
        });

        future.handle(new BiFunction<Void, Throwable, Object>() {
            @Override
            public Object apply(Void unused, Throwable throwable) {
                if (null == throwable) {
                    System.out.println("没有发生异常.");
                }else {
                    System.out.println("发生了异常.");
                }
                return null;
            }
        });

        System.out.println(future.get());
    }
}

执行结果:

根据的结果是否抛出异常回调不同的方法.两种处理合并在了一个方法中.

runAsync方法:

可以参考前面的文章.

handle方法:

typescript 复制代码
 public <U> CompletableFuture<U> handle(
        BiFunction<? super T, Throwable, ? extends U> fn) {
        return uniHandleStage(null, fn);
    }

函数式接口BiFunction:

typescript 复制代码
@FunctionalInterface
public interface BiFunction<T, U, R> {

    /**
     * Applies this function to the given arguments.
     *
     * @param t the first function argument
     * @param u the second function argument
     * @return the function result
     */
    R apply(T t, U u);

    /**
     * Returns a composed function that first applies this function to
     * its input, and then applies the {@code after} function to the result.
     * If evaluation of either function throws an exception, it is relayed to
     * the caller of the composed function.
     *
     * @param <V> the type of output of the {@code after} function, and of the
     *           composed function
     * @param after the function to apply after this function is applied
     * @return a composed function that first applies this function and then
     * applies the {@code after} function
     * @throws NullPointerException if after is null
     */
    default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t, U u) -> after.apply(apply(t, u));
    }
}

函数式接口BiFunction理解:

1.apply方法就是接收两个泛型参数,然后由子类实现.

2.andThen方法.提供了默认实现.接收一个Function的实现对象,然后调用他的方法.

uniHandleStage方法:

typescript 复制代码
  private <V> CompletableFuture<V> uniHandleStage(
        Executor e, BiFunction<? super T, Throwable, ? extends V> f) {
        if (f == null) throw new NullPointerException();
        CompletableFuture<V> d = new CompletableFuture<V>();
        if (e != null || !d.uniHandle(this, f, null)) {
            UniHandle<T,V> c = new UniHandle<T,V>(e, d, this, f);
            push(c);
            c.tryFire(SYNC);
        }
        return d;
    }

uniHandleStage方法理解:

其余的像push方法 tryFire方法可以参考前面的文章.

uniHandle方法:

ini 复制代码
   final <S> boolean uniHandle(CompletableFuture<S> a,
                                BiFunction<? super S, Throwable, ? extends T> f,
                                UniHandle<S,T> c) {
        Object r; S s; Throwable x;
        if (a == null || (r = a.result) == null || f == null)
            return false;
        if (result == null) {
            try {
                if (c != null && !c.claim())
                    return false;
                if (r instanceof AltResult) {
                    x = ((AltResult)r).ex;
                    s = null;
                } else {
                    x = null;
                    @SuppressWarnings("unchecked") S ss = (S) r;
                    s = ss;
                }
                completeValue(f.apply(s, x));
            } catch (Throwable ex) {
                completeThrowable(ex);
            }
        }
        return true;
    }

uniHandle方法理解:

get方法可以参考前面文章.

链式运用:

csharp 复制代码
public class completableFutures_supplyAsync {
    public static void main(String[] args) throws InterruptedException {

        CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
                System.out.println("返回a");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "a";
        }).applyToEitherAsync(CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
                System.out.println("返回b");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "b";
        }), res -> res).whenCompleteAsync((res, err) -> System.out.println("最快返回:" + res));
        TimeUnit.SECONDS.sleep(10);
    }
}

执行结果:

supplyAsync方法:

可以参考前面有返回值的异步操作.

applyToEitherAsync方法:

typescript 复制代码
 public <U> CompletableFuture<U> applyToEitherAsync(
        CompletionStage<? extends T> other, Function<? super T, U> fn) {
        return orApplyStage(asyncPool, other, fn);
    }

applyToEitherAsync方法理解:

函数接口前面有讲解.

orApplyStage方法:

typescript 复制代码
  private <U extends T,V> CompletableFuture<V> orApplyStage(
        Executor e, CompletionStage<U> o,
        Function<? super T, ? extends V> f) {
        CompletableFuture<U> b;
        if (f == null || (b = o.toCompletableFuture()) == null)
            throw new NullPointerException();
        CompletableFuture<V> d = new CompletableFuture<V>();
        if (e != null || !d.orApply(this, b, f, null)) {
            OrApply<T,U,V> c = new OrApply<T,U,V>(e, d, this, b, f);
            orpush(b, c);
            c.tryFire(SYNC);
        }
        return d;
    }

orApplyStage方法理解:

orApply方法:

typescript 复制代码
    final <R,S extends R> boolean orApply(CompletableFuture<R> a,
                                          CompletableFuture<S> b,
                                          Function<? super R, ? extends T> f,
                                          OrApply<R,S,T> c) {
        Object r; Throwable x;
        if (a == null || b == null ||
            ((r = a.result) == null && (r = b.result) == null) || f == null)
            return false;
        tryComplete: if (result == null) {
            try {
                if (c != null && !c.claim())
                    return false;
                if (r instanceof AltResult) {
                    if ((x = ((AltResult)r).ex) != null) {
                        completeThrowable(x, r);
                        break tryComplete;
                    }
                    r = null;
                }
                @SuppressWarnings("unchecked") R rr = (R) r;
                completeValue(f.apply(rr));
            } catch (Throwable ex) {
                completeThrowable(ex);
            }
        }
        return true;
    }

orApply方法理解:

关于跳转可以了解一下下面这个demo.跑一下结果就理解了.

ini 复制代码
public class JumpToTest {
    
        public static void main(String[] args) {
            label1:
            for (int i = 1; i <=5; i++) {
                for (int j = 1; j <= 10; j++) {
                    if (j == 5)
                        break label1;
                    System.out.print(j+" ");
                }
            }
            //结果 1 2 3 4
            System.out.println();
            System.out.println("*******************");

            label2:
            for (int i = 1; i <=5; i++) {
                for (int j = 1; j <= 5; j++) {
                    if (j == 2)
                        continue label2;
                    System.out.print(j+" ");
                }
            }
            //结果 1 1 1 1 1
            System.out.println();
            System.out.println("*******************");

            for (int i = 1; i <=5; i++) {
                for (int j = 1; j <= 5; j++) {
                    if (j == 2)
                        continue;
                    System.out.print(j+" ");
                }
            }
            System.out.println();
            System.out.println("*******************");
            //结果 1 3 4 5 1 3 4 5 1 3 4 5 1 3 4 5 1 3 4 5
            for (int i = 1; i <=5; i++) {
                for (int j = 1; j <= 5; j++) {
                    if (j == 2)
                        break;
                    System.out.print(j+" ");

                }
            }
            //结果 1 1 1 1 1
        }
}

whenCompleteAsync方法:

swift 复制代码
public CompletableFuture<T> whenCompleteAsync(
        BiConsumer<? super T, ? super Throwable> action) {
        return uniWhenCompleteStage(asyncPool, action);
    }

函数式接口BiConsumer:

java 复制代码
/**
 * Represents an operation that accepts two input arguments and returns no
 * result.  This is the two-arity specialization of {@link Consumer}.
 * Unlike most other functional interfaces, {@code BiConsumer} is expected
 * to operate via side-effects.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #accept(Object, Object)}.
 *
 * @param <T> the type of the first argument to the operation
 * @param <U> the type of the second argument to the operation
 *
 * @see Consumer
 * @since 1.8
 */
@FunctionalInterface
public interface BiConsumer<T, U> {

    /**
     * Performs this operation on the given arguments.
     *
     * @param t the first input argument
     * @param u the second input argument
     */
    void accept(T t, U u);

    /**
     * Returns a composed {@code BiConsumer} that performs, in sequence, this
     * operation followed by the {@code after} operation. If performing either
     * operation throws an exception, it is relayed to the caller of the
     * composed operation.  If performing this operation throws an exception,
     * the {@code after} operation will not be performed.
     *
     * @param after the operation to perform after this operation
     * @return a composed {@code BiConsumer} that performs in sequence this
     * operation followed by the {@code after} operation
     * @throws NullPointerException if {@code after} is null
     */
    default BiConsumer<T, U> andThen(BiConsumer<? super T, ? super U> after) {
        Objects.requireNonNull(after);

        return (l, r) -> {
            accept(l, r);
            after.accept(l, r);
        };
    }
}

函数式接口BiConsumer理解:

1.accept函数就是接收两个参数,然后执行我们实现的任务.

2.执行完accept方法以后,在链式调用传入的accept方法.

uniWhenCompleteStage方法:

typescript 复制代码
   private CompletableFuture<T> uniWhenCompleteStage(
        Executor e, BiConsumer<? super T, ? super Throwable> f) {
        if (f == null) throw new NullPointerException();
        CompletableFuture<T> d = new CompletableFuture<T>();
        if (e != null || !d.uniWhenComplete(this, f, null)) {
            UniWhenComplete<T> c = new UniWhenComplete<T>(e, d, this, f);
            push(c);
            c.tryFire(SYNC);
        }
        return d;
    }

uniWhenCompleteStage方法理解:

uniWhenComplete方法:

ini 复制代码
   final boolean uniWhenComplete(CompletableFuture<T> a,
                                  BiConsumer<? super T,? super Throwable> f,
                                  UniWhenComplete<T> c) {
        Object r; T t; Throwable x = null;
        if (a == null || (r = a.result) == null || f == null)
            return false;
        if (result == null) {
            try {
                if (c != null && !c.claim())
                    return false;
                if (r instanceof AltResult) {
                    x = ((AltResult)r).ex;
                    t = null;
                } else {
                    @SuppressWarnings("unchecked") T tr = (T) r;
                    t = tr;
                }
                f.accept(t, x);
                if (x == null) {
                    internalComplete(r);
                    return true;
                }
            } catch (Throwable ex) {
                if (x == null)
                    x = ex;
            }
            completeThrowable(x, r);
        }
        return true;
    }

uniWhenComplete方法理解:

get方法可以参考前面的文章.如果有哪里不明了,可以从第一篇文章看起.好多盲点会清晰很多.

语雀地址www.yuque.com/itbosunmian...?

《Go.》 密码:xbkk 欢迎大家访问.提意见.

无言独上西楼,月如钩,寂寞梧桐深院锁清秋,剪不断,理还乱,别是一番滋味在心头.

相关推荐
香山上的麻雀10081 小时前
由 Rust 开发的能大幅降低LLM token消耗的高性能 CLI 代理工具 rtk
开发语言·后端·rust
神奇小汤圆2 小时前
Java vs Go:哈希冲突解决之道,为什么一个用红黑树,一个用桶?
后端
神奇小汤圆2 小时前
得物二面:Redis 中某个 Key 访问量特别大怎么办?我:Redis 能顶得住... 生瓜蛋子 生瓜蛋子
后端
掘金者阿豪2 小时前
Spring Data JPA 接入金仓数据库:少写代码,多干活
前端·后端
Moment2 小时前
AI 时代,为什么全栈项目越来越离不开 Monorepo 和 TypeScript
前端·javascript·后端
神奇小汤圆2 小时前
字节一面凉了!被问接口超时频繁,线程池该怎么优化?面试官:你管这叫高并发优化?
后端
Jenlybein2 小时前
用 uv 替代 conda,速度飙升(从 0 到 1 开始使用 uv)
后端·python·算法
用户298698530143 小时前
Java 提取 HTML 文本内容:两种轻量级实现方案对比
java·后端
程序边界3 小时前
行标识符的秘密:OID和ROWID的技术演进之路
后端