一 介绍

  • 在Java8中,CompletableFuture提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,并且提供了函数式编程的能力,可以通过回调的方式处理计算结果,也提供了转换和组合 CompletableFuture 的方法。
  • 它实现了两个接口 FutureCompletionStage
    • Future
      • Future接口定义了操作异步任务执行一些方法,如获取异步任务的执行结果、取消任务的执行、判断任务是否被取消、判断任务执行是否完毕等。
      • 只能通过阻塞或者轮询的方式得到任务的结果 调用get()会阻塞
    • CompletionStage
      • 代表异步计算过程中的某一个阶段,一个阶段完成以后可能会触发另外一个阶段
  • 它取代了FutureTask , FutureTask实现的是FutureRunnable接口

    二 四个核心静态方法

    runAsync

  • public static CompletableFuture runAsync(Runnable runnable)

  • public static CompletableFuture runAsync(Runnable runnable,Executor executor)

    supplyAsync

  • public static CompletableFuture supplyAsync(Supplier supplier

  • public static CompletableFuture supplyAsync(Supplier supplier,Executor executor)

    说明

    没有指定Executor的方法,直接使用默认的ForkJoinPool.commonPool() 作为它的线程池执行异步代码,注意主线程结束后其默认线程池会结束

    三 上手

    Lambda+Stream+函数式编程

    1. public static List<String> getPriceByASync(List<Mall> list)
    2. {
    3. return list
    4. .stream()
    5. .map(mall -> CompletableFuture.supplyAsync(() ->System.out.println(mall.getPrice())
    6. .collect(Collectors.toList())
    7. .stream()
    8. .map(CompletableFuture::join)
    9. .collect(Collectors.toList());
    10. }
    11. //异步编排 如多线程爬虫

    四 常用方法分类

    4.1获得结果和触发计算

  • get()

  • get(long timeout, TimeUnit unit)
  • getNow(T valueIfAbsent)
    • 立刻获取结果不阻塞,若未完成计算则返回valueIfAbsent
  • join()

    • 与get()用法相同,但join()方法抛出的是uncheck异常(即未经检查的异常),不会强制开发者抛出会将异常包装成CompletionException异常 /CancellationException异常,但是本质原因还是代码内存在的真正的异常
    • get()方法抛出的是经过检查的异常,ExecutionException, InterruptedException 需要用户手动处理(抛出或者 try catch)

      4.2对计算结果进行处理

  • thenApply 计算结果存在依赖关系

  • handle 根据异常参数进行进一步处理

    4.3对计算结果进行消费

  • thenRun(Runnable runnable)

    • 任务 A 执行完执行 B,并且 B 不需要 A 的结果
  • thenAccept(Consumer action)
    • 任务 A 执行完执行 B,B 需要 A 的结果,但是任务 B 无返回值
  • thenApply(Function fn)

    • 任务 A 执行完执行 B,B 需要 A 的结果,同时任务 B 有返回值

      4.4对计算速度进行选用

  • applyToEither

    • 谁快用谁

      4.5对计算结果进行合并

  • thenCombine