1.Java 异步编程的线程线程完美利器:CompletableFuture 指北
2.奇*巧技,CompletableFuture 异步多线程是池a池源真的优雅
3.研发必会-异步编程利器之CompletableFuture(含源码 中)
4.源码细读-深入了解terser-webpack-plugin的实现
5.CompletableFuture详解
6.åè°CompletableFutureä¹å¾ªç¯å建并å线ç¨
Java 异步编程的完美利器:CompletableFuture 指北
在Java异步编程领域,CompletableFuture是源码不可或缺的利器。本文旨在深入探讨CompletableFuture,线程线程以解答其为何能成为异步编程的池a池源完美解决方案。
在讨论Future获取异步执行结果之前,源码手机lua源码下载我们先了解Future接口及其常用方法。线程线程Future接口提供了丰富的池a池源功能,包括取消任务、源码判断任务状态以及获取结果的线程线程方法。
通过Future接口,池a池源我们能使用FutureTask类将Callable任务转化为可执行的源码异步任务,并在必要时获取任务结果。线程线程然而,池a池源Future与FutureTask在实际应用中存在不足,源码如缺乏异步回调机制、无法主动完成或取消任务、阻塞式获取结果以及异常处理的灵活性问题。
为解决这些不足,Java引入了CompletableFuture,提供更丰富的功能,如异步回调、任务组合、时序依赖关系描述以及异常处理。CompletableFuture通过多种方法创建任务,如使用Runnable、Supplier接口,以及默认使用的ForkJoinPool线程池。
在处理任务依赖关系时,CompletableFuture提供了描述串行、AND汇聚、OR汇聚以及异常处理的收付app源码接口。通过thenApply、thenAccept、thenRun和thenCompose等方法,我们能清晰描述任务的串行执行关系。
对于AND汇聚关系,我们可以使用thenCombine、thenAcceptBoth或runAfterBoth等接口;而对于OR汇聚关系,applyToEither、acceptEither或runAfterEither等接口则能实现这一目的。这些方法允许我们灵活地组合和处理异步任务。
异常处理在异步编程中尤为重要,CompletableFuture通过简单易用的方法,如exceptionally、whenComplete和handle等,帮助我们捕获并处理异常。这些方法允许我们以链式编程的方式,优雅地处理异步操作中的异常情况。
获取异步结果时,我们有多种选择,如get、join、whenComplete、handle、allOf和anyOf等方法。这些方法提供了灵活的接口,以适应不同的异步获取需求。例如,allOf方法允许我们在所有任务完成时触发操作,而anyOf方法则等待任意一个任务完成。
通过以上内容,我们全面理解了CompletableFuture在Java异步编程中的桌面特效源码作用,它不仅解决了Future与FutureTask的不足,还提供了丰富的功能,以支持更复杂的异步编程场景。CompletableFuture是Java异步编程的完美利器,值得开发者深入研究和掌握。
奇*巧技,CompletableFuture 异步多线程是真的优雅
在处理多线程异步任务时,Java的Future接口虽然提供了一定的异步执行能力,但获取结果的方式并不优雅。传统的Future.get()会导致线程阻塞,或通过轮询检查完成状态。当涉及到多个异步任务依赖时,CountDownLatch可以解决,但Java 8之后,CompletableFuture的引入带来了更为优雅的解决方案。
CompletableFuture不仅能够轻松实现CountDownLatch的功能,还能实现更复杂的任务依赖和回调机制。比如,任务A完成后立即执行任务B,甚至任务A的结果可以作为任务B的参数。四种常见的创建方式,如supplyAsync和runAsync,提供了异步执行任务的不同途径。
获取结果的方式也有四种,包括thenRun/thenRunAsync(无返回值回调)、thenAccept/thenAcceptAsync(回调方法接受结果,无返回)、thenApply/thenApplyAsync(回调方法接收结果并返回)、以及异常处理的whenComplete和exceptionally。它们允许在任务完成或出错时执行特定操作。
多任务组合回调提供了AND和OR的bt c 源码关系,如thenCombine、applyToEither等,允许任务之间复杂的依赖关系。但需要注意,如果没有正确配置线程池,如使用默认的ForkJoin线程池,可能会导致性能问题或任务被丢弃。
使用CompletableFuture时,还需注意Future获取返回值时可能的异常信息、get()方法的阻塞性、以及推荐使用自定义线程池和避免饱和策略导致的任务丢弃。这些细节将确保异步编程的高效和优雅。
研发必会-异步编程利器之CompletableFuture(含源码 中)
微信公众号访问地址: 研发必会-异步编程利器之CompletableFuture(含源码 中)
近期热推文章:
1、springBoot对接kafka,批量、并发、异步获取消息,并动态、批量插入库表;
2、SpringBoot用线程池ThreadPoolTaskExecutor异步处理百万级数据;
3、基于Redis的Geo实现附近商铺搜索(含源码)
4、基于Redis实现关注、取关、共同关注及消息推送(含源码)
5、SpringBoot整合多数据源,并支持动态新增与切换(详细教程)
6、基于Redis实现点赞及排行榜功能
7、研发必会-异步编程利器之CompletableFuture(上)
一、多任务组合回调
备注:源码获取方式在文底。
1.1、AND组合关系
thenCombine / thenAcceptBoth / runAfterBoth都表示:将两个CompletableFuture组合起来,只有这两个都正常执行完了,才会执行某个任务。php商品源码也即:当任务一和任务二都完成再执行任务三(异步任务)。
区别在于:
1、runAfterBoth:不会把执行结果当做方法入参,且没有返回值。
2、thenAcceptBoth:会将两个任务的执行结果作为方法入参,传递到指定方法中,且无返回值。
3、thenCombine:会将两个任务的执行结果作为方法入参,传递到指定方法中,且有返回值。
代码案例:
运行结果:
1.2、OR组合关系
将两个CompletableFuture组合起来,只要其中一个执行完了,就会执行某个任务。(两个任务,只要有一个任务完成,就执行任务三)
区别在于:
1、runAfterEither:不会把执行结果当做方法入参,且没有返回值。
2、acceptEither: 会将已经执行完成的任务,作为方法入参,传递到指定方法中,且无返回值。
3、applyToEither:会将已经执行完成的任务,作为方法入参,传递到指定方法中,且有返回值。(个人推荐)
参考代码:
返回结果:
若将异步任务中的Thread.sleep()改为,将输出的结果为:
从结果中不难对比发现,任务的参数是任务和任务中执行最快的返回结果。
注意:若把核心线程数量改为1,会是什么样的呢?
运行结果:
从上面看出,改为1就变成单线程执行了。
1.3、多任务组合(allOf\anyOf)
1.allOf:等待所有任务都执行完成后,才会执行 allOf 返回的CompletableFuture。如果任意一个任务异常,allOf的CompletableFuture,执行get方法,会抛出异常。(等待所有任务完成才会执行)
2.anyOf:任意一个任务执行完,就执行anyOf返回的CompletableFuture。如果执行的任务异常,anyOf的CompletableFuture,执行get方法,会抛出异常。(只要有一个任务完成)
参考案例:
结果返回:
从结果中看出:等待所有任务都执行完成后,才会执行 allOf 返回的CompletableFuture。
同理anyOf,只需要调整代码:
运行结果:
1.4、thenCompose
thenCompose方法会在某个任务执行完成后,将该任务的执行结果,作为方法入参,去执行指定的方法。该方法会返回一个新的CompletableFuture实例。
1、如果该CompletableFuture实例的result不为null,则返回一个基于该result新的CompletableFuture实例;
2、如果该CompletableFuture实例为null,然后就执行这个新任务。
代码案例:
结果:
二、使用注意点
CompletableFuture 使异步编程更加便利的、代码更加优雅的同时,也要关注使用的一些注意点。
2.1、Future需要获取返回值,才能获取异常信息
代码案例:
输出结果:
Future需要获取返回值(res.get()),才能获取到异常信息。如果不加 get()/join()方法,看不到异常信息。使用的时候,注意一下,考虑是否加try…catch…或者使用exceptionally方法。
若改成exceptionally方法,无需get或join也可以捕获异常信息:
结果:
2.2、CompletableFuture的get()方法是阻塞的
CompletableFuture的get()方法是阻塞的,如果使用它来获取异步调用的返回值,需要添加超时时间。
推荐使用:
2.3、建议使用自定义线程池,不要使用默认的
CompletableFuture代码中使用了默认的线程池,处理的线程个数是电脑CPU核数-1。在大量请求过来的时候,处理逻辑复杂的话,响应会很慢。一般建议使用自定义线程池,优化线程池配置参数。
参考案例:
但是如果线程池拒绝策略是DiscardPolicy或者DiscardOldestPolicy,当线程池饱和时,会直接丢弃任务,不会抛弃异常。因此建议,CompletableFuture线程池策略最好使用AbortPolicy,然后耗时的异步线程,做好线程池隔离。
说明:
AbortPolicy(默认):直接抛弃
CallerRunsPolicy:用调用者的线程执行任务
DiscardOldestPolicy:抛弃队列中最久的任务
DiscardPolicy:抛弃当前任务。
三、源码获取方式
更多优秀文章,请关注个人微信公众号或搜索“程序猿小杨”查阅。然后回复:源码,可以获取对应的源码,开箱即可使用。
如果大家对相关文章感兴趣,可以关注微信公众号"程序猿小杨",会持续更新优秀文章!欢迎大家 分享、收藏、点赞、在看,您的支持就是我坚持下去的最大动力!谢谢!
参考网站:
blog.csdn.net/ThinkWon/...
mp.weixin.qq.com/s/shjA...
源码细读-深入了解terser-webpack-plugin的实现
terser-webpack-plugin 是一个基于 webpack 的插件,它利用 terser 库对 JavaScript 代码进行压缩和混淆。其核心功能在于通过在 webpack 的运行时钩子 optimizeChunkAssets 中注册,实现了代码优化过程。在 apply 函数中,它获取 compilation 实例,并通过 tapPromise 注册一个异步任务,当 webpack 执行优化阶段时,每个 chunk 会触发这个任务,执行 minify 函数进行压缩处理。
optimise 函数是实际的任务处理入口,它负责具体的优化流程。函数内部,scheduleTask 负责并行处理,如果开启 parallel 模式,会利用jest-worker提供的线程池进行并发工作,线程池管理复杂,根据 node 版本不同采用 worker_threads 或 child_process。minify 函数则是压缩和混淆代码的核心操作,它直接使用 terser 库完成任务。
总的来说,terser-webpack-plugin 的优化流程包括在 webpack 的优化阶段对代码进行压缩,使用 Jest 的 worker 线程池进行并行处理,以及通过 terser 库的实际压缩操作。理解这些核心环节,可以帮助开发者更深入地掌握该插件的使用和工作原理。
CompletableFuture详解
CompletableFuture详解
CompletableFuture是Java中强大的并发工具,它在Future的基础上引入了流式编程和Lambda表达式,支持一元操作符、异步性和事件驱动模型,尤其在处理多线程关系上表现出色。相较于Future,CompletableFuture提供了更大的灵活性和功能。创建方式
使用默认线程池:如`CompletableFuture future = new CompletableFuture>();`,默认采用ForkJoinPool.commonPool(),适用于非阻塞的CPU密集型任务。
自定义线程池:用户可根据需要创建自定义线程池。
操作示例
- **异步任务**:
runAsync:无返回值,处理数据但不返回结果。
supplyAsync:有返回值,处理数据并返回结果。
- **结果消费**:
thenApply:有返回值,基于前一阶段结果执行操作。
thenAccept:无返回值,只消费结果。
thenRun:无返回值,与前一阶段同步执行。
- **结果合并**:
thenCombine:有返回值,结合另一个任务结果返回新结果。
thenAcceptBoth:无返回值,等待第一个任务完成并传递结果。
runAfterBoth:无返回值,两个任务并行执行。
- **任一结果处理**:
applyToEither:有返回值,接收任一任务结果并转换。
acceptEither:无返回值,消费任一任务结果。
runAfterEither:无返回值,任一任务完成后执行。
实战应用
- API网关:用于并行聚合接口返回,耗时以最慢接口为准。
与其他方法的区别
- whenComplete和handle:前者类似finally,无论是否异常都执行,后者允许返回结果。
- thenApply与thenCompose:前者处理已完成Future的结果,后者计算并返回另一个Future。
- Async的区别:无Async在特定线程执行,有Async在ForkJoinPool.commonPool()中异步执行。
以上是CompletableFuture的基本介绍和常见操作,它在并发编程中提供高效且灵活的解决方案。
åè°CompletableFutureä¹å¾ªç¯å建并å线ç¨
åè¨
å¨ä¹åä¸ç¯æç« ãå©ç¨CompletableFutureåå¤çº¿ç¨å¹¶åæä½ãéï¼ä»ç»äºå¦ä½ä½¿ç¨CompletableFutureè¿è¡å¤çº¿ç¨å¹¶åæä½ï¼ä½æ¯éå®äºå¹¶åçå线ç¨ä¸ªæ°ä¸ºä¸ä¸ªç¡®å®å¼ï¼å¨ä»£ç å±é¢å°±åºå®äºãå½å¹¶åçå线ç¨æ°éä¸åºå®æ¶ï¼é£ä¹ï¼ä¹åçç¨æ³å°±æ æ³ç»§ç»ä½¿ç¨ï¼æ¤æ¶éè¦æ¢ä¸ä¸ªç¨æ³ã
循ç¯å建并å线ç¨åºæ¬æè·¯åºæ¬æè·¯æ¯ï¼å°ææçå线ç¨ä»»å¡éè¿å¾ªç¯çæ¹å¼æ¾å ¥å°ä¸ä¸ªList<CompletableFuture>éï¼æ ¹æ®ä¸å¡çåºæ¯ï¼éæ©ä¸åçæ¹æ³ï¼
ææå线ç¨é½éè¦å®æååæ§è¡ä¸»çº¿ç¨
CompletableFuture.allOf().join()
å ¶ä¸ä»»ä½ä¸ä¸ªå线ç¨å®æåå°±æ§è¡ä¸»çº¿ç¨
ComPletableFuture.anyOf()
ä¸ä»£ç ä¸å¡åºæ¯ï¼æ ¹æ®ä¸ä¼ çå¤ä¸ªè¡æ¿åºç¼ç ï¼adCodeï¼å¹¶åæ¥è¯¢å¤©æ°ä¿¡æ¯ã
å 为qWeatherByCode()æ¹æ³æè¿åå¼ï¼æ以éè¦ä½¿ç¨CompletableFuture.supplyAsync()æ¹æ³ã
该æ¹æ³è¿åä¸ä¸ªCompletableFuture对象ï¼ç¶åå å ¥å°List<CompletableFuture>对象éã
ç¶å使ç¨CompletableFuture.allOf().join()æ¹æ³ï¼å½è°ç¨è¯¥æ¹æ³æ¶ï¼ä¸»çº¿ç¨ä¼ä¸ç´é»å¡ï¼ç´å°List<CompletableFuture>éçå线ç¨åå·²å®æï¼æè è¶ æ¶ï¼ã
List<CompletableFuture>futures=newArrayList();for(StringadCode:adCodeList){ futures.add(CompletableFuture.supplyAsync(()->qWeatherByCode(adCode)));}CompletableFuture.allOf(futures.toArray(newCompletableFuture[futures.size()])).join();éè¦æ³¨æçæ¯ï¼ä¸é¢ç代ç éCompletableFuture.supplyAsync(()->qWeatherByCode(adCode))ï¼æ²¡ææå®Executorï¼æ以使ç¨é»è®¤ç线ç¨æ± ForkJoinPool.commonPool()ã
ForkJoinPool.commonPool()æ¯ä¸ä¸ªå ±äº«çº¿ç¨æ± ï¼åºäºæå¡å¨å æ ¸çéå¶ï¼å¦æCPUæ¯å «æ ¸ï¼æ¯æ¬¡çº¿ç¨åªè½èµ·å «ä¸ªï¼ä¸è½èªå®ä¹çº¿ç¨æ± ï¼ï¼å¦æ使ç¨ä¸å½ï¼ä¼å¯¹æ§è½é æ严éçå½±åãæ以ä¸è¬å»ºè®®è¿é使ç¨èªå®ä¹çExecutor:
List<CompletableFuture>futures=newArrayList();for(StringadCode:adCodeList){ futures.add(CompletableFuture.supplyAsync(()->qWeatherByCode(adCode),asyncExecutor()));}CompletableFuture.allOf(futures.toArray(newCompletableFuture[futures.size()])).join();asyncExecutor():
@Bean("asyncExcutor")publicExecutorasyncExecutor(){ log.info("startasyncexecutor");ThreadPoolTaskExecutorthreadPoolTaskExecutor=newThreadPoolTaskExecutor();//é ç½®æ ¸å¿çº¿ç¨æ°threadPoolTaskExecutor.setCorePoolSize(ThreadPoolConstant.CORE_POOL_SIZE);//é ç½®æ大线ç¨æ°threadPoolTaskExecutor.setMaxPoolSize(ThreadPoolConstant.MAX_POOL_SIZE);//é ç½®éå大å°threadPoolTaskExecutor.setQueueCapacity(ThreadPoolConstant.QUEUE_CAPACITY);//é 置线ç¨æ± ä¸çº¿ç¨çå称åç¼threadPoolTaskExecutor.setThreadNamePrefix(ThreadPoolConstant.THREAD_NAME_PREFIX);//HelloWorldServiceImplrejection-policy:å½poolå·²ç»è¾¾å°maxsizeæ¶ï¼å¦ä½å¤çæ°ä»»å¡ï¼//CallerRunsPolicy:ä¸å¨æ°çº¿ç¨ä¸æ§è¡ä»»å¡ï¼èæ¯ç±è°ç¨è æå¨ç线ç¨æ¥æ§è¡ï¼//AbortPolicy:æç»æ§è¡æ°ä»»å¡ï¼å¹¶æåºRejectedExecutionExceptionå¼å¸¸ï¼//DiscardPolicyï¼ä¸¢å¼å½åå°è¦å å ¥éåçä»»å¡ï¼//DiscardOldestPolicyï¼ä¸¢å¼ä»»å¡éåä¸ææ§çä»»å¡ï¼threadPoolTaskExecutor.setRejectedExecutionHandler(newThreadPoolExecutor.CallerRunsPolicy());threadPoolTaskExecutor.initialize();returnthreadPoolTaskExecutor;}CompletableFutureç常ç¨åºæ¯packagecom.example.demo;importorg.junit.Test;importjava.util.Arrays;importjava.util.List;importjava.util.Random;importjava.util.concurrent.*;/***Project<demo-project>*Createdbyjorgezhongon/9/:.*/publicclassCompletableFutureDemo{ /***å建CompletableFuture*-runAsync*-supplyAsync*-completedFuture*<p>*å¼æ¥è®¡ç®å¯ç¨ç线ç¨æ± æ¯å®æ¤çº¿ç¨*/@Testpublicvoidtest1(){ //1ãå¼æ¥è®¡ç®ï¼æ è¿åå¼//é»è®¤çº¿ç¨æ± 为ï¼ForkJoinPool.commonPool()CompletableFuture.runAsync(()->{ //TODO:/9/8æ è¿åå¼æ¥è®¡ç®System.out.println(Thread.currentThread().isDaemon());});//æå®çº¿ç¨æ± ï¼ï¼å°äºjdk9CompletableFutureè¿æå±äºå»¶è¿ç线ç¨æ± ï¼CompletableFuture.runAsync(()->{ //TODO:/9/8æ è¿åå¼æ¥è®¡ç®},Executors.newFixedThreadPool(2));//2ãå¼æ¥è®¡ç®ï¼æè¿åå¼//使ç¨é»è®¤çº¿ç¨æ± CompletableFuture<String>future1=CompletableFuture.supplyAsync(()->"result1");//getNowæå®å¼æ¥è®¡ç®æåºå¼å¸¸æç»æè¿ånullæ¶æ¿ä»£ççå¼Stringresult1=future1.getNow(null);//æå®çº¿ç¨æ± CompletableFuture<String>future2=CompletableFuture.supplyAsync(()->"result2",Executors.newFixedThreadPool(2));//getNowæå®å¼æ¥è®¡ç®æåºå¼å¸¸æç»æè¿ånullæ¶æ¿ä»£ççå¼Stringresult2=future2.getNow(null);//3ãåå§åä¸ä¸ªæç»ææ 计ç®çCompletableFutureCompletableFuture<String>future=CompletableFuture.completedFuture("result");Stringnow=future.getNow(null);System.out.println("now="+now);}/***计ç®å®ææ¶éè¦å¯¹å¼å¸¸è¿è¡å¤çæè 对ç»æè¿è¡å¤ç*-whenCompleteï¼åæ¥å¤çå æ¬å¼å¸¸*-thenApplyï¼åæ¥å¤çæ£å¸¸ç»æï¼åææ¯æ²¡æå¼å¸¸ï¼*<p>*-whenCompleteAsyncï¼å¼æ¥å¤çå æ¬å¼å¸¸*-thenApplyAsyncï¼å¼æ¥å¤çæ£å¸¸ç»æ(åææ¯æ²¡æå¼å¸¸)*<p>*-exceptionally:å¤çå¼å¸¸*/@Testpublicvoidtest2(){ CompletableFuture<String>future=CompletableFuture.supplyAsync(()->"result");//whenCompleteæ¹æ³æ¶futureçç»æåå¼å¸¸ï¼å¯çµæ´»è¿è¡å¤ç//1ãåæ¥å¤ç//æ è¿åå¼ï¼å¯å¤çå¼å¸¸future.whenComplete((result,throwable)->System.out.println("result="+result));//æè¿åå¼ï¼æ²¡æå¼å¸¸å¤çï¼åæï¼CompletableFuture<String>resultFuture1=future.thenApply(result->"result");Stringresult1=resultFuture1.getNow(null);//2ãå¼æ¥å¤çï¼//æ è¿åå¼ï¼é»è®¤çº¿ç¨æ± future.whenCompleteAsync((result,throwable)->System.out.println("result="+result));//æ è¿åå¼ï¼æå®çº¿ç¨æ± future.whenCompleteAsync((result,throwable)->System.out.println("result="+result),Executors.newFixedThreadPool(2));//æè¿åå¼ï¼é»è®¤çº¿ç¨æ± CompletableFuture<String>resultFuture2=future.thenApplyAsync(result->"result");Stringresult2=resultFuture2.getNow(null);//æè¿åå¼ï¼æå®çº¿ç¨æ± CompletableFuture<String>resultFuture3=future.thenApplyAsync(result->"result",Executors.newFixedThreadPool(2));Stringresult3=resultFuture3.getNow(null);//3ãå¤çå¼å¸¸,å¤çå®ä¹åè¿åä¸ä¸ªç»æCompletableFuture<String>exceptionallyFuture=future.whenCompleteAsync((result,throwable)->System.out.println("result="+1/0)).exceptionally(throwable->"åçå¼å¸¸äºï¼"+throwable.getMessage());System.out.println(exceptionallyFuture.getNow(null));}/***å¼å¸¸å¤çè¿å¯ä»¥ä½¿ç¨ä»¥ä¸ä¸¤ä¸ªæ¹æ³*-handle*-handleAsync*<p>*å¤æ³¨ï¼exceptionallyåæ¥åå¼æ¥è®¡ç®ä¸èµ·ç¨å¦æåºç°å¼å¸¸ä¼æå¼å¸¸æåºãç¨ä»¥ä¸çæ¹æ³å¯ä»¥æ¦æªå¤ç*/@Testpublicvoidtest3(){ CompletableFuture<String>exceptionoHandle=CompletableFuture.completedFuture("producemsg").thenApplyAsync(s->"result"+1/0);StringhandleResult1=exceptionoHandle.handle((s,throwable)->{ if(throwable!=null){ returnthrowable.getMessage();}returns;}).getNow(null);//æå®çº¿ç¨æ± StringhandleResult2=exceptionoHandle.handleAsync((s,throwable)->{ if(throwable!=null){ returnthrowable.getMessage();}returns;},Executors.newFixedThreadPool(2)).getNow(null);}/***ç产--æ¶è´¹*-thenAcceptï¼åæ¥ç*-thenAcceptAsyncï¼å¼æ¥ç*<p>*æ¥åä¸ä¸ä¸ªå¤çç»æï¼å¹¶å®ç°ä¸ä¸ªConsumer,æ¶è´¹ç»æ*/@Testpublicvoidtest4(){ //åæ¥çCompletableFuture.completedFuture("producemsg").thenAccept(s->System.out.println("syncconsumedmsg:"+s));//å¼æ¥ç//é»è®¤çº¿ç¨æ± CompletableFuture.completedFuture("producemsg").thenAcceptAsync(s->System.out.println("asyncconsumedmsg:"+s));//æå®çº¿ç¨æ± CompletableFuture.completedFuture("producemsg").thenAcceptAsync(s->System.out.println("asyncconsumedmsg:"+s),Executors.newFixedThreadPool(2));}/***åæ¶ä»»å¡*-cancel*/@Testpublicvoidtest5()throwsInterruptedException{ CompletableFuture<String>message=CompletableFuture.completedFuture("message").thenApplyAsync(s->{ try{ Thread.sleep();}catch(InterruptedExceptione){ e.printStackTrace();}returns+"result";});Stringnow=message.getNow(null);System.out.println("now="+now);//åæ¶booleancancel=message.cancel(true);System.out.println("cancel="+cancel);//å¦æè¿éåå»è·åï¼ä¼æåºå¼å¸¸ï¼è¯´æå·²ç»åæ¶äº//Stringnow1=message.getNow(null);Thread.sleep();}/***两个å¼æ¥è®¡ç®*-applyToEitherï¼æè¿åå¼,åæ¥*-acceptEitherï¼æ è¿åå¼ï¼åæ¥*-applyToEitherAsync:æè¿åå¼ï¼å¼æ¥*-*/@Testpublicvoidtest6(){ CompletableFuture<String>task1=CompletableFuture.completedFuture("task1").thenApply(s->"task1ç计ç®ç»æï¼s1="+s);//åæ¥ï¼æè¿åå¼//applyToEither第äºä¸ªåæ°æ¥æ¶çå¼æ¯task1计ç®çè¿åå¼CompletableFuture<String>result1=task1.applyToEither(CompletableFuture.completedFuture("task2").thenApply(s->"task2ç计ç®ç»æï¼s2="+s),s->s);System.out.println("task2:"+result1.getNow(null));//åæ¥ï¼æ è¿åå¼task1.acceptEither(CompletableFuture.completedFuture("task3").thenApply(s->"task3ç计ç®ç»æï¼s3="+s),s->System.out.println("task3ï¼"+s));//å¼æ¥æè¿åå¼ï¼é»è®¤çº¿ç¨æ± ï¼ä¹å¯ä»¥æå®CompletableFuture<String>result2=task1.applyToEitherAsync(CompletableFuture.completedFuture("task4").thenApply(s->"task4ç计ç®ç»æï¼s4="+s),s->s);//ç±äºæ¯å¼æ¥çï¼ä¸»çº¿ç¨è·çå¿«ä¸ç¹ï¼å æ¤join()ä¹åæè½çå°è·å®çç»æSystem.out.println("task4:"+result2.join());//å¼æ¥æ è¿åå¼,æå®çº¿ç¨æ± ,ä¹å¯ä»¥ä½¿ç¨é»è®¤çº¿ç¨æ± CompletableFuture<Void>task5=task1.acceptEitherAsync(CompletableFuture.completedFuture("task5").thenApply(s->"task5ç计ç®ç»æï¼s5="+s),s->System.out.println("task5ï¼"+s),Executors.newFixedThreadPool(2));task5.join();}/***ç»å计ç®ç»æ*-runAfterBothï¼é½è®¡ç®å®ä¹åæ§è¡ä¸æ®µä»£ç *-thenAcceptBothï¼é½è®¡ç®å®ä¹åæç»æä¼ å ¥ï¼å¹¶æ§è¡ä¸æ®µä»£ç *<p>*-thenCombineï¼ç»å两个ç»æ*-thenComposeï¼ç»å两个ç»æ*/@Testpublicvoidtest7(){ //runAfterBothæ¹å¼StringBuildermsg=newStringBuilder("jorgeZhong");CompletableFuture.completedFuture(msg).thenApply(s->s.append("task1,")).runAfterBoth(CompletableFuture.completedFuture(msg).thenApply(s->s.append("task2")),()->System.out.println(msg));//thenAcceptBothæ¹å¼CompletableFuture.completedFuture("jorgeZhong").thenApplyAsync(String::toLowerCase).thenAcceptBoth(CompletableFuture.completedFuture("jorgeZhong").thenApplyAsync(String::toUpperCase),(s,s2)->System.out.println("s1:"+s+",s2:"+s2));//thenCombineæ¹å¼CompletableFuture<String>result1=CompletableFuture.completedFuture("jorgeZhong").thenApply(String::toLowerCase).thenCombine(CompletableFuture.completedFuture("jorgeZhong").thenApply(String::toUpperCase),(s,s2)->"s1:"+s+",s2:"+s2);System.out.println("result1:"+result1.getNow(null));//å¼æ¥CompletableFuture<String>result=CompletableFuture.completedFuture("jorgeZhong").thenApply(String::toLowerCase).thenCombineAsync(CompletableFuture.completedFuture("jorgeZhong").thenApplyAsync(String::toUpperCase),(s,s2)->"s1:"+s+",s2:"+s2);System.out.println("result:"+result.join());//thenComposeæ¹å¼CompletableFuture<String>result2=CompletableFuture.completedFuture("jorgeZhong").thenApply(String::toLowerCase).thenCompose(s->CompletableFuture.completedFuture("jorgeZhong").thenApply(String::toUpperCase).thenApply(s1->"s:"+s+",s1:"+s1));System.out.println("result2:"+result2.getNow(null));//å¼æ¥CompletableFuture<String>result=CompletableFuture.completedFuture("jorgeZhong").thenApply(String::toLowerCase).thenComposeAsync(s->CompletableFuture.c