CompletableFuture

官方文档

A Future that may be explicitly completed (setting its value and 
status), and may be used as a CompletionStage, supporting 
dependent functions and actions that trigger upon its 
completion.

When two or more threads attempt to complete, 
completeExceptionally, or cancel a CompletableFuture, only one 
of them succeeds.

In addition to these and related methods for directly 
manipulating status and results, CompletableFuture implements 
interface CompletionStage with the following policies:
* Actions supplied for dependent completions of non-async 
  methods may be performed by the thread that completes the 
  current CompletableFuture, or by any other caller of a 
  completion method.
* All async methods without an explicit Executor argument are 
  performed using the ForkJoinPool.commonPool() (unless it 
  does not support a parallelism level of at least two, in which 
  case, a new Thread is created to run each task). To simplify 
  monitoring, debugging, and tracking, all generated 
  asynchronous tasks are instances of the marker interface 
  CompletableFuture.AsynchronousCompletionTask.
* All CompletionStage methods are implemented independently 
  of other public methods, so the behavior of one method is not 
  impacted by overrides of others in subclasses.

CompletableFuture also implements Future with the following 
policies:
* Since (unlike FutureTask) this class has no direct control over 
  the computation that causes it to be completed, cancellation is 
  treated as just another form of exceptional completion. Method 
  cancel has the same effect as completeExceptionally(new 
  CancellationException()). Method isCompletedExceptionally() 
  can be used to determine if a CompletableFuture completed in 
  any exceptional fashion.
* In case of exceptional completion with a CompletionException, 
  methods get() and get(long, TimeUnit) throw an 
  ExecutionException with the same cause as held in the 
  corresponding CompletionException. To simplify usage in most 
  contexts, this class also defines methods join() and getNow(T) 
  that instead throw the CompletionException directly in these 
  cases.

可以显式完成的Future(设置其值和状态),并且可以用作CompletionStage,支持在完成时触发依赖函数和操作。

Future的不足

Future是Java5添加的类, 用来描述一个异步计算的结果。你可以使用isDone 方法检查计算是否完成,或者使用 get 阻塞住调用线程,直到计算完成返回结果, 你也可以使用 cancel 方法停止任务的执行。

虽然 Future 以及相关使用方法提供了异步执行任务的能力,但是对于结果 的获取却是很不方便,只能通过阻塞或者轮询的方式得到任务的结果。阻塞的方 式显然和我们的异步编程的初衷相违背,轮询的方式又会耗费无谓的 CPU 资源, 而且也不能及时地得到计算结果,为什么不能用观察者设计模式当计算结果完成 及时通知监听者呢?

Java 的一些框架,比如 Netty,自己扩展了 Java 的 Future 接口,提供了 addListener 等多个扩展方法,Googleguava 也提供了通用的扩展 Future:ListenableFuture、SettableFuture 以及辅助类 Futures 等,方便异步编程。

同时 Future 接口很难直接表述多个 Future 结果之间的依赖性。实际开发中, 我们经常需要达成以下目的:

  • 将两个异步计算合并为一个——这两个异步计算之间相互独立,同时第二个 又依赖于第一个的结果。
  • 等待 Future 集合中的所有任务都完成。
  • 仅等待 Future 集合中最快结束的任务完成(有可能因为它们试图通过不同 的方式计算同一个值),并返回它的结果。
  • 应对 Future 的完成事件(即当 Future 的完成事件发生时会收到通知,并 能使用 Future 计算的结果进行下一步的操作,不只是简单地阻塞等待操作的结 果)

CompletableFuture

JDK1.8 才新加入的一个实现类 CompletableFuture,实现了 Future,CompletionStage两个接口。实现了 Future 接口,意味着可以像以 前一样通过阻塞或者轮询的方式获得结果。

创 建

除了直接 new 出一个 CompletableFuture 的实例,还可以通过工厂方法创建 CompletableFuture 的实例

工厂方法:

在这里插入图片描述
Asynsc表示异步,而supplyAsync与runAsync不同在与前者异步返回一个结果, 后者是 void.第二个函数第二个参数表示是用我们自己创建的线程池,否则采用默 认的 ForkJoinPool.commonPool()作为它的线程池。

获得结果的方法
public Tget() 
public Tget(longtimeout,TimeUnitunit) 
public TgetNow(TvalueIfAbsent) 
public Tjoin() 

getNow 有点特殊,如果结果已经计算完则返回结果或者抛出异常,否则返 回给定的 valueIfAbsent 值。

join 返回计算的结果或者抛出一个 unchecked 异常(CompletionException),它 和 get 对抛出的异常的处理有些细微的区别。

参见代码

/**
 * 类说明:CompletableFuture使用范例
 */
public class CFDemo {

    static class GetResult extends Thread {
        CompletableFuture<Integer> f;
        GetResult(String threadName, CompletableFuture<Integer> f) {
            super(threadName);
            this.f = f;
        }
        @Override
        public void run() {
            try {
                System.out.println("waiting result.....");
                System.out.println(this.getName() + ": " + f.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws Exception {
        final CompletableFuture<Integer> f = new CompletableFuture<>();

        new GetResult("Client1", f).start();
        new GetResult("Client2", f).start();
        System.out.println("sleeping");
        SleepTools.second(2);
        //f.complete(100);
        f.completeExceptionally(new Exception());
        System.in.read();
    }
}
get和join方法的区别
/**
 * 类说明:get和join方法的区别
 */
public class JoinAndGet {
    public static void main(String[] args)
            throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(()->{
           int i = 1/0;
           return 100;
        });
        //future.get();
        future.join();
    }
}
辅助方法
public static CompletableFuture<Void>allOf(CompletableFuture<?>...cfs) 
public static CompletableFuture<Object>anyOf(CompletableFuture<?>...cfs)
  • allOf 方法是当所有的 CompletableFuture 都执行完后执行计算。
  • anyOf 方法是当任意一个 CompletableFuture 执行完后就会执行计算,计算的 结果相同。
/**
 * 类说明:allOf和anyOf的区别
 */
public class AllofAnyOf {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Random rand = new Random();
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000 + rand.nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("future1完成");
            return 100;
        });
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000 + rand.nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("future2完成");
            return "abc";
        });
        CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000 + rand.nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("future3完成");
            return "123abc";
        });
        CompletableFuture.allOf(future1,future2,future3).thenRun(()->{
            System.out.println("All done!");
        });

//        CompletableFuture<Object> f = CompletableFuture.anyOf(future1,future2,future3);
//        System.out.println(f.get());

        SleepTools.second(5);
    }
}

CompletionStage 是一个接口,从命名上看得知是一个完成的阶段,它代表 了一个特定的计算的阶段,可以同步或者异步的被完成。你可以把它看成一个计 算流水线上的一个单元,并最终会产生一个最终结果,这意味着几个 CompletionStage 可以串联起来,一个完成的阶段可以触发下一阶段的执行,接 着触发下一次,再接着触发下一次,……….。

总结 CompletableFuture 几个关键点:

  1. 计算可以由 Future ,Consumer 或者 Runnable 接口中的 apply,accept 或者 run 等方法表示。
  2. 计算的执行主要有以下
    a. 默认执行
    b. 使用默认的 CompletionStage 的异步执行提供者异步执行。这些方法名使 用 someActionAsync 这种格式表示。
    c. 使用 Executor 提供者异步执行。这些方法同样也是 someActionAsync 这 种格式,但是会增加一个 Executor 参数。
CompletableFuture 里大约有五十种方法,但是可以进行归类
变换类 thenApply

在这里插入图片描述
关键入参是函数式接口 Function。它的入参是上一个阶段计算后的结果,返 回值是经过转化后结果。

消费类 thenAccept

在这里插入图片描述
关键入参是函数式接口 Consumer。它的入参是上一个阶段计算后的结果, 没有返回值。

执行操作类 thenRun

在这里插入图片描述
对上一步的计算结果不关心,执行下一个操作,入参是一个 Runnable 的实 例,表示上一步完成后执行的操作。

结合转化类

在这里插入图片描述
需要上一步的处理返回值,并且 other 代表的 CompletionStage 有返回值之 后,利用这两个返回值,进行转换后返回指定类型的值。
两个 CompletionStage 是并行执行的,它们之间并没有先后依赖顺序,other 并不会等待先前的 CompletableFuture 执行完毕后再执行。

结合转化类

在这里插入图片描述
对于 Compose 可以连接两个 CompletableFuture,其内部处理逻辑是当第一 个CompletableFuture处理没有完成时会合并成一个CompletableFuture,如果处理 完成,第二个 future 会紧接上一个 CompletableFuture 进行处理。

第一个 CompletableFuture 的处理结果是第二个 future 需要的输入参数。

结合消费类

在这里插入图片描述
需要上一步的处理返回值,并且 other 代表的 CompletionStage 有返回值之 后,利用这两个返回值,进行消费

运行后执行类

在这里插入图片描述
不关心这两个 CompletionStage 的结果,只关心这两个 CompletionStage 都执 行完毕,之后再进行操作(Runnable)。

取最快转换类

在这里插入图片描述
两个 CompletionStage,谁计算的快,我就用那个 CompletionStage 的结果进 行下一步的转化操作。现实开发场景中,总会碰到有两种渠道完成同一个事情, 所以就可以调用这个方法,找一个最快的结果进行处理。

取最快消费类

在这里插入图片描述
两个 CompletionStage,谁计算的快,我就用那个 CompletionStage 的结果进 行下一步的消费操作。

取最快运行后执行类

在这里插入图片描述
两个 CompletionStage,任何一个完成了都会执行下一步的操作(Runnable)。

异常补偿类

在这里插入图片描述
当运行时出现了异常,可以通过 exceptionally 进行补偿。

运行后记录结果类

在这里插入图片描述
action 执行完毕后它的结果返回原始的 CompletableFuture 的计算结果或者返回 异常。所以不会对结果产生任何的作用。

运行后处理结果类

在这里插入图片描述
运行完成时,对结果的处理。这里的完成时有两种情况,一种是正常执行, 返回值。另外一种是遇到异常抛出造成程序的中断。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一名技术极客

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

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

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

打赏作者

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

抵扣说明:

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

余额充值