JUC : ExecutorService → CompletionService → CompletableFuture 进化史

原博客链接:Notion – The all-in-one workspace for your notes, tasks, wikis, and databases.

衍化过程

  • 最开始使用多线程的时候,继承Thread 实现Runnable接口属三无产品,无法传入参数、无发接收返回值、无法捕捉异常;
  • 所以衍生出实现Callable接口,有返回值可以捕捉异常。使用callable开启多线程,需要Callable任务借助FutureTask,或者与线程池一起 ,返回Future再get。但是存在get Future的资源时,出现同步阻塞现象;
  • 又一次在current包下衍生了CompletionService接口,更优雅的解决线程池批量异步任务的执行与获取解耦。

ExecutorService

三种submit的方式

三种submit的方式

Untitled

虽然继承的是Runnable,但是通过自己的拓展也可以返回结果

虽然继承的是Runnable,但是通过自己的拓展也可以返回结果

Untitled

Untitled

Untitled

  • 为何ExecutorService**.**submit()可以获取到返回值? Executor ****Callable/Runnable与Future的关系? submit的提交过程?

    <aside> ⚠️ Executor就是Runnable和Callable的调度容器, Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果、设置结果操作。

    </aside>

    • ExecutorService.submit() 向线程池提交任务的时候,返回的是Future<T> ,但是Future实际上是接口,具体的是返回的是FutureTask<T>,它实现了Runnable 与 Future接口。
    • 在submit提交的时候,无论是Runnable还是Callable,底层都会被封装成FutureTask,即使你提交了Runnable代码,也是会被适配器模式的工厂方法转换为Callable类型,存入属性中
    • 虽然FutureTask继承了Runnable接口,重写了run方法后无法直接获取返回值,但是通过run方法中调用自己底层封装好的的set方法就可以将结果存在Object类型的 outcome 全局变量中,提供get方法来进行线程结果的获取。

ExecutorService的弊端

  • 直接创建的线程池使用,在后续循环调用Future,Future.get方法,但如果这个Future的任务没有执行完成,那么get就会被阻塞。 导致多线程执行任务的时候,可能先get到了一个长任务,导致后面的短任务全部被阻塞,这样后面已经完成的任务就没法获得结果了。 这时候就需要CompletionService来处理这种情况。
  • 适用于并行计算的结果做汇总,或者并行计算间有关联的情况。

CompletionService 与 ExecutorCompletionService 未完成

  • ExecutorCompletionService,内部依靠LinkedBlockingQueue的实现多线程任务的管理,还有一个传统的ExecutorService线程池进行任务执行(作为参数传入的线程池)。
  • ExecutorCompletionService 需要传入一个线程池(Executor顶级接口作为参数),所以直接new的ThreadPoolExecutor 还是通过ExecutorService工厂创建的都可以(底层返回的也是ThreadPoolExecutor

CompletableFurute 异步回调链式编排 未完成

ForkJoinPool 工作窃取算法线程池

异步回调处理

调用链

链式回调

graph LR
 A["CompletableFuture.supplyAsync()"] --> D["allOf()"]
 B["CompletableFuture.supplyAsync()"] --> D
 C["CompletableFuture.supplyAsync()"] --> D
 D --> E["thenApplyAsync()"]

supplyAsync / runAsync —> allOf / anyOf  —> than + Apply / Accept / Run + Async (join / get)

CODE

1. supplyAsync与runAsync + [ ForkJoinPool / ThreadPoolExecutor ]

supplyAsync 执行有返回值的异步任务,接收一个Supplier,返回一个CompletableFuture对象,可获取异步任务的结果。

runAsync 执行没有返回值的异步任务,接收一个Runnable,返回一个CompletableFuture<Void>对象,表示异步任务执行完毕。

2. anyOf与allOf

3. thenApply / thenAccept / thenRun (Async)

  • thenApply用于处理和转换CompletableFuture的结果。
    • 有参数 , 没有返回值
  • thenAccept用于消费CompletableFuture的结果,不返回新的CompletableFuture。
    • 有参数 , 没有返回值
  • thenRun则不关心前一个任务的结果,只是在前一个任务执行完后,执行一些后续操作。
    • 没参数 ,没有返回值

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值