一、背景
在一些接口响应时间的优化中有一些任务是可以异步处理的,常常会用到这个线程池。但是有一些业务需要依赖异步任务的结果,那么就需要用到 CompletableFuture 或者 FutureTask ,或者在一些多任务并发执行的时候,CompletableFuture 可以提供一些方法让我们更容易的控制并发编程。
二、常见的错误操作
这种就是画蛇添足的做法,等于脱裤子放屁。

第二种方式是把一些业务代码放在 get()方法之前去执行。这种是 oK 的,但是还有一个问题。如果异步任务是 IO 密集型,那么就需要解决线程池的问题。

第三种:使用额外的线程池,处理这个 IO 密集型任务。

总结
使用 CompletableFuture 、FutureTask 的前提:
- 你的业务有异步的需求且需要知道任务执行的结果。比如是否执行完成,执行结果。
- 你的整个业务链中有不依赖这个异步任务结果的业务代码,这样就可以先执行这些中间业务代码。
- 这个中间业务代码( IO 阻塞或者非阻塞代码,非阻塞代码一般很快)的执行时间 W ,W 最好大于或者等于这个异步任务的执行时间。如果 W 执行很快,比如是非阻塞代码,那么这个异步任务的意义不大。
注意事项:
- 如果这个异步任务是一个非阻塞代码(也就是计算密集型代码),那么直接用即可(底层是 ForkJoinPool)。这个在就不再阐述原理了,在线程池那集有讲过。
- 如果这个异步任务是一个 IO 阻塞型代码,那么就需要使用一个额外的自定义线程池去处理,这个线程池的大小取决于这个任务的 IO 和 cpu 时间比,还有和中间任务的时间比,大致确定范围即可。
这些问题的详细描述在我的 B 站里 ,java 并发编程: https://www.bilibili.com/video/BV1CA4y1S7Pe? 这些都是 API 的使用,其实很无聊。但是错的人太多了,所以就讲一下这个问题。头大。。
其他的场景就是多个任务同步执行的情况,可以使用 allOf ,compose 等,那么就不在这里给大家演示了。