原博客链接: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的方式
虽然继承的是Runnable,但是通过自己的拓展也可以返回结果
-
为何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.submit() 向线程池提交任务的时候,返回的是
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
则不关心前一个任务的结果,只是在前一个任务执行完后,执行一些后续操作。- 没参数 ,没有返回值