java8之CompletableFuture的源码的跟踪(二)

在上一节中,了解了关于CompletableFuture执行异步任务的方法,但是这些方法在执行完异步任务之后,这个异步任务的结果怎么

获取呢?

在CompletableFuture异步任务执行完之后,返回的是一个CompletableFuture对象,在以前Future时代,我们通过future.get()获取其

异步任务执行的结果,但是这个方法是阻塞的,也就是说:当你future.get()的时候,请求线程是阻塞的(主线程{父线程}),必须等待

子线程完成结果以后,才会执行主线程的任务,此时其实是同步的,所以为了改进CompletableFuture做了..

类结构:

public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {}

在执行完异步任务之后,我们理解下面的回调函数:

1.从有没有返回值的角度去分析:

1.public <U> CompletableFuture<U> thenApply(
    Function<? super T,? extends U> fn) {
    return uniApplyStage(null, fn);
}
2.public CompletableFuture<Void> thenAccept(Consumer<? super T> action) {
    return uniAcceptStage(null, action);
}
3.public CompletableFuture<Void> thenRun(Runnable action) {
    return uniRunStage(null, action);
}
private <V> CompletableFuture<V> uniApplyStage(
    Executor e, Function<? super T,? extends V> f) {
    if (f == null) throw new NullPointerException();
    CompletableFuture<V> d =  new CompletableFuture<V>();
    if (e != null || !d.uniApply(this, f, null)) {
        UniApply<T,V> c = new UniApply<T,V>(e, d, this, f);
        push(c);
        c.tryFire(SYNC);
    }
    return d;
}

一个关键的因素不要忘记:如果没有用户(程序员本身)没有创建线程池,则会默认的使用forkJoin,

有没有返回值,关键是从入参开始:

1.thenApply接受的是一个Function<? super T,? extends U> fn,而Function本身是一个函数式的接口如下,重点是apply方法,传入一个

T,返回一个R,这个是泛型的类型

@FunctionalInterface
public interface Function<T, R> {

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);
}
2.thenAccept接受的是一个Consumer<? super T> action,而Consumer本身也是一个函数式的接口,顾名思义,是消费,传入一个T类型

没有返回值

@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);
}

3.thenRun(Runnable action)同理上面的

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}
至于其他的方法道理都是一样的,

即:不管是异步还是同步,都有一个线程池的参数对象

比如:

public <U> CompletableFuture<U> thenApplyAsync(
    Function<? super T,? extends U> fn) {
    return uniApplyStage(asyncPool, fn);
}

public <U> CompletableFuture<U> thenApplyAsync(
    Function<? super T,? extends U> fn, Executor executor) {
    return uniApplyStage(screenExecutor(executor), fn);
}
比如:
当一个线程依赖另一个线程时,可以使用 thenApply 方法来把这两个线程串行化。
Function<? super T,? extends U>
T:上一个任务返回结果的类型
U:当前任务的返回值类型

private static void thenApply() throws ExecutionException, InterruptedException {
    CompletableFuture<Long> future = CompletableFuture.supplyAsync(() -> {
        long result = new Random().nextInt(100);
        System.out.println("result : " + result);
        return result;
    }).thenApply((res) -> {
        System.out.println("res "+ res);
       return res*5;
    });
    Long aLong = future.get();
    System.out.println(aLong);

 

总体的一个思路是:

异步任务的执行底层是用线程池实现的,而异步任务的回调是通过上面的方法实现的,而最终的结果时什么呢?

下面继续...

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值