JDK源码之CompletableFuture(一)结果返回原理
JDK源码之CompletableFuture(二)链式调用原理
JDK源码之CompletableFuture(三)anyOf,allOf是怎么实现的?
在jdk8中有一个并发类,叫做CompletableFuture,它的出现可以说功能上基本可以取代CountDownLatch,CyclicBarrier,信号量等等的功能,并且可以做到链式调用,非常的好用,可以 说会了这个CompletableFuture,并掌握其原理,你基本可以应付你工作中所有的并发问题。
一、CompletableFuture抬手第一步
CompletableFuture有两个方法创建,分别是:
CompletableFuture.runAsync();
CompletableFuture.supplyAsync();
区别就是一个有返回结果,一个没有返回结果。
- 线程池参数:可以不传,不传就用默认的ForkJoinPool;
注意: 尽量用自己创建的线程池,因为ForkJoinPool中创建的线程池默认是后台线程,图示如下:
在主线程退出时,后台线程也就结束了,会发生预想不到的问题。可以在主线程中用future的get()方法获取结果来阻塞,但是作为一位好的程序员,结合业务自定义线程池是必备的技能点。
二、CompletableFuture是如何获取返回结果的?
在线程池执行的时候,使用了这么一个类AsyncSupply
e.execute(new AsyncSupply<U>(d, f));
这个类定义如下:
static final class AsyncSupply<T> extends ForkJoinTask<Void>
implements Runnable, AsynchronousCompletionTask {
既然能被线程池执行,我们直接看其run方法:
public void run() {
CompletableFuture<T> d; Supplier<T> f;
if ((d = dep) != null && (f = fn) != null) {
dep = null; fn = null;
if (d.result == null) {
try {
d.completeValue(f.get());
} catch (Throwable ex) {
d.completeThrowable(ex);
}
}
d.postComplete();
}
}
- 可以看到获取到结果后,会有一个completeValue方法,将结果设置到result参数上
- 而Future.get()就是在轮询result的值,直到result的值不为空就获取到结果了。
三、总结
这次我们从源码角度说了
- CompletableFuture创建使用线程池和不使用线程池的方式
- CompletableFuture返回结果的原理
后面一篇文章,我们开始聊聊CompletableFuture是如何实现链式调用的