返回顶部
首页 > 资讯 > 精选 >怎么使用CompletableFuture
  • 638
分享到

怎么使用CompletableFuture

2023-06-15 16:06:15 638人浏览 独家记忆
摘要

这篇文章主要讲解了“怎么使用CompletableFuture”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用CompletableFuture”吧!但Future机制,还不那么灵活,

这篇文章主要讲解了“怎么使用CompletableFuture”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用CompletableFuture”吧!

怎么使用CompletableFuture

但Future机制,还不那么灵活,比如怎么去利用Future机制描述两个任务串行执行,又或是两个任务并行执行,又或是只关心最先执行结束的任务结果。

Future机制在一定程度上都无法快速地满足以上需求,CompletableFuture便应运而生了。

1. 创建一个异步任务

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)   public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor);   public static CompletableFuture<Void> runAsync(Runnable runnable);   public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor);

supplyAsync与runAsync的区别在于:supplyAsync有返回值,而runAsync没有返回值

带Executor参数的构造函数,则使用线程池中的线程执行异步任务(线程池可以参考说说线程池)

不带Executor参数的构造函数,则使用ForkJoinPool.commonPool()中的线程执行异步任务(Fork/Join框架可以参考谈谈并行流parallelStream)

1.1 示例:使用supplyAsync创建一个有返回值的异步任务

public class Case1 {      public static void main(String[] args) throws Exception {          CompletableFuture<Integer> completableFuture=CompletableFuture.supplyAsync(()->{             try {                 Thread.sleep(1000);             } catch (InterruptedException e) {                 e.printStackTrace();             }             return 1;         });         //该方法会一直阻塞         Integer result = completableFuture.get();         System.out.println(result);     }  }

2. 异步任务的回调

public CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action);    public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action);    public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action, Executor executor);    public CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn);

whenComplete开头的方法在计算任务完成(包括正常完成与出现异常)之后会回调

而exceptionally则只会在计算任务出现异常时才会被回调

如何确定哪个线程去回调whenComplete,比较复杂,先略过。

而回调whenCompleteAsync的线程比较简单,随便拿一个空闲的线程即可,后缀是Async的方法同理。

2.1 示例:计算出现异常,使用whenComplete与exceptionally进行处理

package com.qcy.testCompleteableFuture;  import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.stream.IntStream;   public class Case2 {      public static void main(String[] args) throws Exception {          CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {             try {                 Thread.sleep(1000);             } catch (InterruptedException e) {                 e.printStackTrace();             }             System.out.println("执行supplyAsync的线程:" + Thread.currentThread().getName());             int i = 1 / 0;             return 1;         });          completableFuture.whenComplete(new BiConsumer<Integer, Throwable>() {             @Override             public void accept(Integer integer, Throwable throwable) {                 System.out.println("执行whenComplete的线程:" + Thread.currentThread().getName());                 if (throwable == null) {                     System.out.println("计算未出现异常,结果:" + integer);                 }             }         });          completableFuture.exceptionally(new Function<Throwable, Integer>() {             @Override             public Integer apply(Throwable throwable) {                 //出现异常时,则返回一个默认值                 System.out.println("计算出现异常,信息:" + throwable.getMessage());                 return -1;             }         });          System.out.println(completableFuture.get());     }  }

输出:

怎么使用CompletableFuture

当然,CompletableFuture内的各种方法是支持链式调用与Lambda表达式的,我们进行如下改写:

public static void main(String[] args) throws Exception {       CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {          try {              Thread.sleep(2000);          } catch (InterruptedException e) {              e.printStackTrace();          }          System.out.println("执行supplyAsync的线程:" + Thread.currentThread().getName());          int i = 1 / 0;          return 1;      }).whenComplete((integer, throwable) -> {          System.out.println("执行whenComplete的线程:" + Thread.currentThread().getName());          if (throwable == null) {              System.out.println("计算未出现异常,结果:" + integer);          }      }).exceptionally(throwable -> {          //出现异常时,则返回一个默认值          System.out.println("计算出现异常,信息:" + throwable.getMessage());          return -1;      });       System.out.println("计算结果:" + completableFuture.get());  }

3. 任务串行化执行

public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn);    public CompletableFuture<Void> thenRun(Runnable action);    public CompletableFuture<Void> thenAccept(Consumer<? super T> action);    public <U> CompletableFuture<U> handle(BiFunction<? super T, Throwable, ? extends U> fn);    public <U> CompletableFuture<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn);

thenApply,依赖上一次任务执行的结果,参数中的Function<? super T,? extends U>,T代表上一次任务返回值的类型,U代表当前任务返回值的类型,当上一个任务没有出现异常时,thenApply才会被调用

thenRun,不需要知道上一个任务的返回结果,只是在上一个任务执行完成之后开始执行Runnable

thenAccept,依赖上一次任务的执行结果,因为入参是Consumer,所以不返回任何值。

handle和thenApply相似,不过当上一个任务出现异常时,能够执行handle,却不会去执行thenApply

thenCompose,传入一次任务执行的结果,返回一个新的CompleteableFuture对象

3.1 示例:使用串行化任务分解两数相乘并输出

package com.qcy.testCompleteableFuture;  import java.util.concurrent.CompletableFuture;   public class Case4 {      public static void main(String[] args) {                  CompletableFuture.supplyAsync(() -> 2)                 .thenApply(num -> num * 3)                 .thenAccept(System.out::print);     }  }

很显然,输出为6

3.2 示例:使用串行化任务并且模拟出现异常

package com.qcy.testCompleteableFuture;  import java.util.concurrent.CompletableFuture; import java.util.function.BiFunction;   public class Case4 {      public static void main(String[] args) {          CompletableFuture.supplyAsync(() -> 2)                 .thenApply(num -> num / 0)                 .thenApply(result -> result * 3)                 .handle((integer, throwable) -> {                     if (throwable == null) {                         return integer;                     } else {                         throwable.printStackTrace();                         return -1;                     }                 }).thenAccept(System.out::print);     }  }

最终会输出-1

4. 任务同时执行,且都需要执行完成

public <U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other, Function<? super T,? super U,? extends V> fn);    public <U> CompletableFuture<Void> thenAcceptBoth(CompletionStage<? extends U> other, Consumer<? super T, ? super U> action);    public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other,Runnable action);    public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs);

thenCombine,合并两个任务,两个任务可以同时执行,都执行成功后,执行最后的BiFunction操作。其中T代表第一个任务的执行结果类型,U代表第二个任务的执行结果类型,V代表合并的结果类型

thenAcceptBoth,和thenCombine特性用法都极其相似,唯一的区别在于thenAcceptBoth进行一个消费,没有返回值

runAfterBoth,两个任务都执行完成后,但不关心他们的返回结构,然后去执行一个Runnable。

allOf,当所有的任务都执行完成后,返回一个CompletableFuture

4.1 示例:使用thenCombine合并任务

package com.qcy.testCompleteableFuture;  import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException;   public class Case5 {      public static void main(String[] args) throws Exception {          CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(() -> {             System.out.println("任务1开始");             try {                 Thread.sleep(3000);             } catch (InterruptedException e) {                 e.printStackTrace();             }             System.out.println("任务1结束");             return 2;         });          CompletableFuture<Integer> cf2 = CompletableFuture.supplyAsync(() -> {             System.out.println("任务2开始");             try {                 Thread.sleep(3000);             } catch (InterruptedException e) {                 e.printStackTrace();             }             System.out.println("任务2结束");             return 3;         });          CompletableFuture<Integer> completableFuture = cf1.thenCombine(cf2, (result1, result2) -> result1 * result2);         System.out.println("计算结果:" + completableFuture.get());     }  }

输出:

可以看到两个任务确实是同时执行的

当然,熟练了之后,直接使用链式操作,代码如下:

package com.qcy.testCompleteableFuture;  import java.util.concurrent.CompletableFuture;   public class Case6 {      public static void main(String[] args) throws Exception {          CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {             System.out.println("任务1开始");             try {                 Thread.sleep(3000);             } catch (InterruptedException e) {                 e.printStackTrace();             }             System.out.println("任务1结束");             return 2;         }).thenCombine(CompletableFuture.supplyAsync(() -> {             System.out.println("任务2开始");             try {                 Thread.sleep(2000);             } catch (InterruptedException e) {                 e.printStackTrace();             }             System.out.println("任务2结束");             return 3;         }), (result1, result2) -> result1 * result2);          System.out.println("计算结果:" + completableFuture.get());     }  }

5. 任务同时执行,且只取最先完成的那个任务

public <U> CompletableFuture<U> applyToEither(CompletionStage<? extends T> other, Function<? super T, U> fn);     public CompletableFuture<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action);     public CompletableFuture<Void> runAfterEither(CompletionStage<?> other,Runnable action);     public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs);

applyToEither,最新执行完任务,将其结果执行Function操作,其中T是最先执行完的任务结果类型,U是最后输出的类型

acceptEither,最新执行完的任务,将其结果执行消费操作

runAfterEither,任意一个任务执行完成之后,执行Runnable操作

anyOf,多个任务中,返回最先执行完成的CompletableFuture

5.1 示例:两个任务同时执行,打印最先完成的任务的结果

package com.qcy.testCompleteableFuture;  import java.util.concurrent.CompletableFuture;   public class Case7 {      public static void main(String[] args) throws Exception {          CompletableFuture<Void> completableFuture = CompletableFuture.supplyAsync(() -> {             System.out.println("任务1开始");             try {                 Thread.sleep(3000);             } catch (InterruptedException e) {                 e.printStackTrace();             }             System.out.println("任务1结束");             return 2;         }).acceptEither(CompletableFuture.supplyAsync(() -> {             System.out.println("任务2开始");             try {                 Thread.sleep(2000);             } catch (InterruptedException e) {                 e.printStackTrace();             }             System.out.println("任务2结束");             return 3;         }), result -> System.out.println(result));          //等待CompletableFuture返回,防止主线程退出         completableFuture.join();     }  }

输出:

怎么使用CompletableFuture

可以看得到,任务2结束后,直接不再执行任务1的剩余代码

5.2 示例:多个任务同时执行,打印最先完成的任务的结果

package com.qcy.testCompleteableFuture;  import java.util.concurrent.CompletableFuture;   public class Case8 {      public static void main(String[] args) throws Exception {          CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(() -> {             System.out.println("任务1开始");             try {                 Thread.sleep(3000);             } catch (InterruptedException e) {                 e.printStackTrace();             }             System.out.println("任务1结束");             return 2;         });          CompletableFuture<Integer> cf2 = CompletableFuture.supplyAsync(() -> {             System.out.println("任务2开始");             try {                 Thread.sleep(2000);             } catch (InterruptedException e) {                 e.printStackTrace();             }             System.out.println("任务2结束");             return 3;         });          CompletableFuture<Integer> cf3 = CompletableFuture.supplyAsync(() -> {             System.out.println("任务3开始");             try {                 Thread.sleep(4000);             } catch (InterruptedException e) {                 e.printStackTrace();             }             System.out.println("任务3结束");             return 4;         });          CompletableFuture<Object> firstCf = CompletableFuture.anyOf(cf1, cf2, cf3);         System.out.println(firstCf.get());     }  }

输出:

怎么使用CompletableFuture

感谢各位的阅读,以上就是“怎么使用CompletableFuture”的内容了,经过本文的学习后,相信大家对怎么使用CompletableFuture这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: 怎么使用CompletableFuture

本文链接: https://lsjlt.com/news/280805.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 怎么使用CompletableFuture
    这篇文章主要讲解了“怎么使用CompletableFuture”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用CompletableFuture”吧!但Future机制,还不那么灵活,...
    99+
    2023-06-15
  • CompletableFuture怎么使用
    这篇文章主要讲解了“CompletableFuture怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“CompletableFuture怎么使用”吧!一个美好的期望通常情况下,我们希望...
    99+
    2023-07-06
  • Java8中CompletableFuture怎么使用
    今天小编给大家分享一下Java8中CompletableFuture怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1...
    99+
    2023-06-29
  • Java8中的CompletableFuture类怎么使用
    本篇内容主要讲解“Java8中的CompletableFuture类怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java8中的CompletableFuture类怎么使用”吧!Java...
    99+
    2023-07-06
  • CompletableFuture的使用
    目录 一、前言 二、概念介绍  三、自身特性 四、使用方式 1、异步执行一个任务并获取结果 2、异步执行一个任务并处理异常 3、异步执行多个任务并合并结果 4、异步执行多个任务并处理其中一个任务的结果 5、串行执行多个任务 6、 检查异步任...
    99+
    2023-09-01
    java
  • CompletableFuture使用详解
    一、简介 1.1 概述 在上一篇文章《CompletionService使用与源码分析》中,已经介绍过了Future的局限性,它没法直接对多个任务进行链式、组合等处理,需要借助并发工具类才能完成,实现逻辑比较复杂。 而Completable...
    99+
    2023-08-16
    java Future
  • Java8并发新特性CompletableFuture怎么使用
    这篇文章主要介绍“Java8并发新特性CompletableFuture怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java8并发新特性CompletableFuture怎么使用”文章能帮...
    99+
    2023-06-30
  • Java CompletableFuture的使用详解
    目录CompletableFuture​任务开启任务结束串行任务thenApply\thenApplyAsync 串行将异步结果进行同步\异步的处理handle\hand...
    99+
    2024-04-02
  • Java 8中CompletableFuture如何使用
    Java 8中CompletableFuture如何使用,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1、创建一个完成的CompletableFuture最简单的例子就是使用一...
    99+
    2023-06-15
  • 详解Java8中CompletableFuture类的使用
    目录创建CompletableFuture处理CompletableFuture的结果处理CompletableFuture的异常总结Java 8中引入了CompletableFut...
    99+
    2023-05-15
    Java8 CompletableFuture类使用 Java8 CompletableFuture类 Java8 CompletableFuture
  • Java8 使用CompletableFuture 构建异步应用方式
    目录概述同步API VS 异步API同步API异步API同步的困扰实现异步API将同步方法改为异步方法处理异常错误概述 为了展示 CompletableFuture 的强大特性, 创...
    99+
    2024-04-02
  • Java中CompletableFuture的作用是什么
    这篇文章给大家介绍Java中CompletableFuture的作用是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。创建CompletableFuture对象。以下四个静态方法用来为一段异步执行的代码创建Compl...
    99+
    2023-06-17
  • Java8中CompletableFuture使用场景与实现原理
    目录1.概述2.为什么引入CompletableFuture3.功能3.源码追踪4.总结1.概述 CompletableFuture是jdk1.8引入的实现类。扩展了Future和C...
    99+
    2024-04-02
  • Java多线程开发工具之CompletableFuture怎么应用
    这篇“Java多线程开发工具之CompletableFuture怎么应用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Jav...
    99+
    2023-07-05
  • Java8如何使用CompletableFuture构建异步应用方式
    小编给大家分享一下Java8如何使用CompletableFuture构建异步应用方式,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!概述为了展示 Completa...
    99+
    2023-06-25
  • Java8 CompletableFuture异步多线程怎么实现
    这篇文章主要介绍了Java8 CompletableFuture异步多线程怎么实现的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java8 CompletableFuture异步多线程怎么实...
    99+
    2023-07-05
  • 分析Java8使用工厂方法supplyAsync创建CompletableFuture
    这篇文章主要介绍“分析Java8使用工厂方法supplyAsync创建CompletableFuture”,在日常操作中,相信很多人在分析Java8使用工厂方法supplyAsync创建CompletableFuture问题上存在疑惑,小编...
    99+
    2023-06-25
  • CompletableFuture使用详解(全网看这一篇就行)
    CompletableFuture是jdk8的新特性。CompletableFuture实现了CompletionStage接口和Future接口,前者是对后者的一个扩展,增加了异步会点、流式处理、多个Future组合处理的能力,使Java...
    99+
    2023-09-12
    java
  • Java8 使用工厂方法supplyAsync创建CompletableFuture实例
    目录使用工厂方法 supplyAsync创建 CompletableFuture对比对CompletableFuture async的理解目前为止我们已经了解了如何通过编程创建 Co...
    99+
    2024-04-02
  • Java8中CompletableFuture的用法全解
    目录前言一、创建异步任务1、Future.submit2、supplyAsync / runAsync二、异步回调1、thenApply / thenApplyA...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作