CompletableFuture是一个异步编程工具类
简单使用
CompletableFuture<String> completableFuture = new CompletableFuture<>();
new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//保存结果
completableFuture.complete("hello world");
}).start();
//获取结果
String result = completableFuture.get();
System.out.println("输出结果:" + result);
CompletableFuture实现了Future接口,所以它调用get()方法的时候会阻塞在那, 直到结果返回。
runAsync方法
//runAsync传入一个runnable,返回一个CompletableFuture
CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
try {
Thread.sleep(2000);
System.out.println("线程执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// 等待线程执行完毕
System.out.println(voidCompletableFuture.get());
System.out.println("程序运行结束");
runAsync()方法的实现原理
public static CompletableFuture<Void> runAsync(Runnable runnable) {
return asyncRunStage(asyncPool, runnable);
}
//判断使用ForkJoinPool还是每过来一个任务创建一个线程执行,这里asyncPool是一个ForkJoinPool
private static final Executor asyncPool = useCommonPool ? ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
//common在ForkJoinPool静态代码块中被初始化
public static ForkJoinPool commonPool() {
// assert common != null : "static init error";
return common;
}
//e是一个ForkJoinPool
static CompletableFuture<Void> asyncRunStage(Executor e, Runnable f) {
if (f == null) throw new NullPointerException();
CompletableFuture<Void> d = new CompletableFuture<Void>();
//封装成AsyncRun,AsyncRun继承了ForkJoinTask,实现了runnable接口,然后执行ForkJoinPool的execute
//如果是supplyAsync这里会封装成一个AsyncSupply
//thenRun封装成UniRun,thenAccept封装成UniAccept,thenApply封装成UniApply然后放到前一个任务的栈里,即后一个任务会被放进前一个任务的CompletableFuture的栈中:unipush(new UniRun<T>...)
e.execute(new AsyncRun(d, f));
return d;
}
AsyncRun(CompletableFuture<Void> dep, Runnable fn) {
this.dep = dep; this.fn = fn;
}
public void execute(Runnable task) {
if (task == null)
throw new NullPointerException();
ForkJoinTask<?> job;
//传入的是一个AsyncRun,AsyncRun继承了ForkJoinTask
if (task instanceof ForkJoinTask<?>) // avoid re-wrap
job = (ForkJoinTask<?>) task;
else
job = new ForkJoinTask.RunnableExecuteAction(task);
//job被转换成ForkJoinTask
externalPush(job);
}
final void externalPush(ForkJoinTask<?> task) {
WorkQueue[] ws; WorkQueue q; int m;
//获得当前线程的探针
int r = ThreadLocalRandom.getProbe();
int rs = runState;
//不会进if
if ((ws = workQueues) != null && (m = (ws.length - 1)) >= 0 &&
(q = ws[m & r & SQMASK]) != null && r != 0 && rs > 0 &&
U.compareAndSwapInt(q, QLOCK, 0, 1)) {
ForkJoinTask<?>[] a; int am, n, s;
if ((a = q.array) != null &&
(am = a.length - 1) > (n = (s = q.top) - q.base)) {
int j = ((am & s) << ASHIFT) + ABASE;
U.putOrderedObject(a, j, task);
U.putOrderedInt(q, QTOP, s + 1);
U.putIntVolatile(q, QLOCK, 0);
if (n <= 1)
signalWork(ws, q);
return;
}
U.compareAndSwapInt(q, QLOCK, 1, 0);
}
//task入队列并执行
externalSubmit(task);
}
private void externalSubmit(ForkJoinTask<?> task) {
int r; // initialize caller's probe