Future
ExecutorService executor = Executors.newFixedThreadPool(4);
// 定义任务:
Callable<String> task = new Task();
// 提交任务并获得Future:
Future<String> future = executor.submit(task);
// 从Future获取异步执行返回的结果:
String result = future.get(); // 可能阻塞
当我们提交一个 Callable
任务后,我们会同时获得一个 Future
对象,然后,我们在主线程某个时刻调用 Future
对象的 get()
方法,就可以获得异步执行的结果。在调用 get()
时,如果异步任务已经完成,我们就直接获得结果。如果异步任务还没有完成,那么 get()
会阻塞,直到任务完成后才返回结果。
一个 Future<V>
接口表示一个未来可能会返回的结果,它定义的方法有:
get()
:获取结果(可能会等待)get(long timeout, TimeUnit unit)
:获取结果,但只等待指定的时间;cancel(boolean mayInterruptIfRunning)
:取消当前任务;isDone()
:判断任务是否已完成。
小结
对线程池提交一个 Callable
任务,可以获得一个 Future
对象;
可以用 Future
在将来某个时刻获取结果。
CompletableFuture
使用 Future
获得异步执行结果时,要么调用阻塞方法 get()
,要么轮询看 isDone()
是否为 true
,这两种方法都不是很好,因为主线程也会被迫等待。
从Java 8开始引入了 CompletableFuture
,它针对 Future
做了改进,可以传入回调对象,当异步任务完成或者发生异常时,自动调用回调对象的回调方法。
public class Main {
public static void main(String[] args) throws Exception {
// 创建异步执行任务:
CompletableFuture<Double> cf = CompletableFuture.supplyAsync(Main::fetchPrice);
// 如果执行成功:
cf.thenAccept((result) -> {
System.out.println("price: " + result);
});
// 如果执行异常:
cf.exceptionally((e) -> {
e.printStackTrace();
return null;
});
// 主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭:
Thread.sleep(200);
}
static Double fetchPrice() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
if (Math.random() < 0.3) {
throw new RuntimeException("fetch price failed!");
}
return 5 + Math.random() * 20;
}
}
CompletableFuture
可以指定异步处理流程:
thenAccept()
处理正常结果;exceptional()
处理异常结果;thenApplyAsync()
用于串行化另一个CompletableFuture
;anyOf()
和allOf()
用于并行化多个CompletableFuture
。
标题:使用Future 和 CompletableFuture
作者:hymn
地址:https://dxyhymn.com/articles/2020/12/04/1607073934695.html