定义
CompletableFuture
,实现了Future
和CompletionStage
public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
...
}
用法
- supplyAsync
supplyAsync(Supplier<U> supplier, Executor executor)
带Async的证明是异步执行,表示有可能会有其它线程来执行,如果不带的证明是由刚刚的线程来执行。
Callable
就是Supplier
的一个实现,Callable的话就代表这个方法可以有返回值
示例
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println("子线程:" + Thread.currentThread() + "执行时间:" + LocalTime.now());
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程:" + Thread.currentThread() + "结束时间:" + LocalTime.now());
return 10;
});
System.out.println("主线程:" + Thread.currentThread() + "执行时间:" + LocalTime.now());
System.out.println(future.get());
System.out.println("主线程:" + Thread.currentThread() + "结束时间:" + LocalTime.now());
// 子线程:Thread[ForkJoinPool.commonPool-worker-1,5,main]执行时间:15:41:10.852
// 主线程:Thread[main,5,main]执行时间:15:41:10.852
// 子线程:Thread[ForkJoinPool.commonPool-worker-1,5,main]结束时间:15:41:12.854
// 10
// 主线程:Thread[main,5,main]结束时间:15:41:12.854
可以看到,效果相当于ExecutorService submit(Callable<T> task)
方法,有返回值
- runAsync
runAsync(Runnable runnable)
也是个异步方法,看入参是个Runnable对象,因此该方法不会有返回值
示例一
CompletableFuture<?> future = CompletableFuture.runAsync(() -> {
System.out.println("子线程:" + Thread.currentThread() + "执行时间:" + LocalTime.now());
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程:" + Thread.currentThread() + "结束时间:" + LocalTime.now());
});
System.out.println("主线程:" + Thread.currentThread() + "执行时间:" + LocalTime.now());
System.out.println(future.get());
System.out.println("主线程:" + Thread.currentThread() + "结束时间:" + LocalTime.now());
// 主线程:Thread[main,5,main]执行时间:15:47:26.958
// 子线程:Thread[ForkJoinPool.commonPool-worker-1,5,main]执行时间:15:47:26.958
// 子线程:Thread[ForkJoinPool.commonPool-worker-1,5,main]结束时间:15:47:28.958
// null
// 主线程:Thread[main,5,main]结束时间:15:47:28.958
可以看到,效果相当于ExecutorService submit(Runnable task)
方法,无返回值
关于ExecutorService的用法,大家可以参考我 这篇文章 中的示例。
Tips
supplyAsync
和runAsync
这两方法各有一个重载版本,可以指定执行异步任务的Executor实现(线程池),如果不指定,默认使用ForkJoinPool.commonPool(),如果机器是单核的,则默认使用ThreadPerTaskExecutor,该类是一个内部类,每次执行execute都会创建一个新线程
示例二 :使用自定义线程池
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<?> future = CompletableFuture.runAsync(() -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, executorService);
System.out.println(future.get());
或者使用默认的ForkJoinPool线程池
ForkJoinPool pool = new ForkJoinPool();
CompletableFuture<Double> future