如何使用CompletableFuture
创始人
2024-04-11 11:55:17
0

目录

一、CompletableFuture是什么

二、CompletableFuture用法

2.1、创建CompletableFuture

2.1.1、直接创建

2.1.2、创建一个使用指定数据作为结果的已结束的CompletableFuture

 2.1.3、通过执行异步任务获取CompletableFuture

 2.2、获取任务结果

2.3、消费结果

2.3.1、whenComplete

2.3.2、thenAccept

2.3.3、thenApply

2.3.4、thenRun

2.3.5、handle

2.3.6、exceptionally

2.4、多任务编排

2.4.1、 依赖(thenCompose)

2.4.2、 AND(thenCombine,thenAcceptBoth,runAfterBoth)

2.4.3、OR(applyToEither)

2.4.4、 并行(allOf,anyOf)


一、CompletableFuture是什么

CompletableFuture是对Future的扩展和增强。CompletableFuture实现了Future接口和CompletionStage使其实现了对任务编排的能力。借助这项能力,可以轻松地组织不同任务的运行顺序、规则以及方式。

二、CompletableFuture用法

2.1、创建CompletableFuture

2.1.1、直接创建

CompletableFuture completableFuture=new CompletableFuture();

2.1.2、创建一个使用指定数据作为结果的已结束的CompletableFuture

CompletableFuture test1 = CompletableFuture.completedFuture("test");

 2.1.3、通过执行异步任务获取CompletableFuture

/*** 使用默认线程池执行异步任务,有返回值*/
CompletableFuture.supplyAsync(() -> "hello CompletableFuture!");
/*** 使用指定线程池执行异步任务,有返回值*/
CompletableFuture.supplyAsync(() -> "Hello CompletableFuture!", Executors.newCachedThreadPool());
/*** 使用默认线程池执行异步任务,无返回值*/
CompletableFuture.runAsync(() -> System.out.println("Hello runAsync!"));
/*** 使用指定线程池执行异步任务,无返回值*/
CompletableFuture.runAsync(() -> System.out.println("Hello RunAsync!"),  Executors.newCachedThreadPool());

 2.2、获取任务结果

方法是否阻塞是否抛出检查异常说明
get()阻塞抛出检查异常
getNow(V value)不阻塞不抛出如果任务没有结束就返回指定的默认值
get(long timeout, TimeUnit unit)阻塞指定时间抛出
join()阻塞不抛出

示例代码: 

        /*** 获取任务结果,阻塞直到任务结束,会抛出检查异常*/String test = CompletableFuture.supplyAsync(() -> "Hello").get();/*** 获取任务结果,如果超过等待之间任务未结束则抛出TimeoutException*/test = CompletableFuture.supplyAsync(() -> "test").get(10, TimeUnit.MILLISECONDS);/*** 如果任务结束则返回任务结果,如果任务未结束则返回指定的默认值*/test = CompletableFuture.supplyAsync(() -> "test").getNow("default");/*** 阻塞获取任务结果,和get相似,但是不会抛出检查异常*/test = CompletableFuture.supplyAsync(() -> "join").join();

2.3、消费结果

2.3.1、whenComplete

whenComplete是当某个任务执行完成后执行的回调方法,不管任务异常还是正常结束都会执行该回调;该回调的入参是任务的执行结果和异常;
如果是正常执行则异常为null,回调方法对应的CompletableFuture的result和该任务一致,如果该任务正常执行,则get方法返回执行结果,如果是执行异常,则get方法抛出异常。

方法说明
 whenComplete(BiConsumer action )在当前线程中同步执行回调操作
 whenCompleteAsync(BiConsumer action )在默认线程池中异步执行回调
 whenCompleteAsync(BiConsumer action,Executor executor )在指定线程池中异步执行回调

 示例代码如下:

 CompletableFuture.supplyAsync(() -> {System.out.println("threadId: " + Thread.currentThread().getId() + ",threadName: " + Thread.currentThread().getName());return "whenComplete";}).whenComplete((a, e) ->System.out.println("threadId: " + Thread.currentThread().getId() + ",threadName: " + Thread.currentThread().getName() + ", a: " + a));CompletableFuture.supplyAsync(()->{throw new RuntimeException("");}).whenComplete((a,e)->System.out.println(e));

执行结果如下:

threadId: 11,threadName: ForkJoinPool.commonPool-worker-9
threadId: 1,threadName: main, a: whenComplete
java.util.concurrent.CompletionException: java.lang.RuntimeException: 

2.3.2、thenAccept

thenAccept只消费正常处理结束的结果,不消费异常同时没有返回值

方法说明
 thenAccept(Consumer action )在当前线程中消费同步消费
thenAcceptAsync(Consumer action )在默认线程池中异步消费
thenAcceptAsync(Consumer action,
    Executor executor )
在指定线程池中异步消费
CompletableFuture.supplyAsync(() -> "thenAccept").thenAccept(str -> System.out.println("threadId: " + Thread.currentThread().getId() + ",threadName: " + Thread.currentThread().getName()+",str="+str));CompletableFuture.supplyAsync(() -> "thenAcceptAsync").thenAcceptAsync(str -> System.out.println("threadId: " + Thread.currentThread().getId() + ",threadName: " + Thread.currentThread().getName()+",str="+str));CompletableFuture.supplyAsync(()->"thenAcceptAsync").thenAcceptAsync(str-> System.out.println("threadId: " + Thread.currentThread().getId() + ",threadName: " + Thread.currentThread().getName()+",str="+str),Executors.newSingleThreadExecutor());

执行结果如下:

threadId: 1,threadName: main,str=thenAccept
threadId: 11,threadName: ForkJoinPool.commonPool-worker-9,str=thenAcceptAsync
threadId: 16,threadName: pool-6-thread-1,str=thenAcceptAsync

2.3.3、thenApply

thenApply和thenAccept的相同点都是消费任务正常结束的结果,不同点就是thenAccept没有返回值而thenApply有返回值。

CompletableFuture.supplyAsync(() -> "Dora").thenApply(str ->"Hello, "+str).thenAccept(System.out::println);
CompletableFuture.supplyAsync(() -> "Dora").thenApplyAsync(str ->"Hello, "+str).thenAccept(System.out::println);
CompletableFuture.supplyAsync(()->"Dora").thenApplyAsync(str ->"Hello, "+str).thenAccept(System.out::println);

执行结果如下:

Hello, Dora
Hello, Dora
Hello, Dora 

2.3.4、thenRun

thenRun和thenAccept相似,都是在任务正常结束后执行且都没有返回值,两者的区别是thenAccept关心上一个任务的结果而thenRun不关心结果。

CompletableFuture.supplyAsync(() -> "thenRun").thenRun(() -> System.out.println("threadId: " + Thread.currentThread().getId() + ",threadName: " + Thread.currentThread().getName()));
CompletableFuture.supplyAsync(() -> "thenRunAsync").thenRunAsync(() -> System.out.println("threadId: " + Thread.currentThread().getId() + ",threadName: " + Thread.currentThread().getName()));
CompletableFuture.supplyAsync(()->"thenRunAsync").thenRunAsync(()-> System.out.println("threadId: " + Thread.currentThread().getId() + ",threadName: " + Thread.currentThread().getName()),Executors.newSingleThreadExecutor());

2.3.5、handle

    handle方法的使用和whenComplete类似

handlewhenComplete
入参任务的结果和异常任务的结果和异常
触发阶段任务结束后,不管正常结束还是异常结束任务结束后,不管正常结束还是异常结束
返回值有返回值Void

2.3.6、exceptionally

exceptionally是当任务执行出现异常时的回调处理,否则不会触发该回调;可以使用whenComplete和handle方法替代该方法

//如果任务执行异常则返回"exception"
CompletableFuture.supplyAsync(()->{throw new RuntimeException("");}).exceptionally((e->"exception")).whenComplete((a,e)->System.out.println(a+" "+e));

执行结果如下:

exception null

2.4、多任务编排

2.4.1、 依赖(thenCompose)

 thenCompose 是依赖前一个任务结果,前一个任务的结果作为当前任务的入参

CompletableFuture.supplyAsync(() -> "hello").thenCompose(p -> CompletableFuture.supplyAsync(() -> p + " world")).thenAccept(System.out::println);

2.4.2、 AND(thenCombine,thenAcceptBoth,runAfterBoth)

thenCombine 是将两个任务的结果进行合并处理

String test = CompletableFuture.supplyAsync(() -> {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {throw new RuntimeException(e);}return "a";}).thenCombineAsync(CompletableFuture.supplyAsync(() -> {try {TimeUnit.SECONDS.sleep(2);} catch (Exception e) {}return "b";}), (a, b) -> a + "_" + b).join();

结果是:

a_b 

thenAcceptBoth和thenCombine比较类似,区别是thenCombine是有返回值,而thenAcceptBoth是消费前两个任务的结果没有返回值

 CompletableFuture.supplyAsync(() -> "hello").thenAcceptBoth(CompletableFuture.supplyAsync(() -> "world"), (a, b) -> {System.out.println(a + "—" + b);});

 结果是:

a-b

runAfterBoth和thenCombine、thenAcceptBoth有所不同,它不关心前两个任务的结果,只要前两个任务都结束就会触发第三个任务执行

CompletableFuture.supplyAsync(() -> "hello").runAfterBoth(CompletableFuture.supplyAsync(() -> "world"), () -> {System.out.println("end");});

结果是

end

2.4.3、OR(applyToEither)

applyToEither从名字上就可以知道两个任务是或的关系,只要有一个任务结束就出发第三个任务执行。

CompletableFuture.supplyAsync(() -> "first").applyToEither(CompletableFuture.supplyAsync(() -> "second"), str ->str + " end").thenAccept(System.out::println);

结果是:

first end 

acceptEither是只要有一个任务结束第三个任务就消费它

CompletableFuture.supplyAsync(() -> "first").acceptEither(CompletableFuture.supplyAsync(() -> "second"), str ->System.out.println(str+" end"));

 

2.4.4、 并行(allOf,anyOf)

          allOf 是所有任务都必须执行结束,anyOf是有一个任务正常结束即可。
 

CompletableFuture.allOf(CompletableFuture.supplyAsync(()->"a"),CompletableFuture.supplyAsync(()->"b")).join();

相关内容

热门资讯

银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...