本文摘抄于《Java8笔记》,如有不明确的地方,请查看原书,仅做笔记用处。
Future
将耗时的操作封装到Callable对象中,然后提交给ExecutorService。
例子如下:
Future<Double> future = executor.submit(new Callable<Double>()){
public Double call(){
return doSomeLongComputation();
}
}
try{
Double result = future.get(1,TimeUnit.SECONDS);
} catch (ExecutionException ee){
//计算抛出一个异常
} catch (InterruptedException ie){
//当前线程在等待过程中被中断
} catch (TimeoutException te){
//在Future对象完成之前超过已过期
}
CompletableFuture
常规处理
public Future<Double> getPriceAsync(String product) {
CompletableFuture<Double> futurePrice = new CompletableFuture<>();
//在另一个线程中以异步方式执行计算
new Thread( () -> {
double price = calculatePrice(product);
//设置future的返回值
futurePrice.complete(price);
}).start();
return futurePrice;
}
/*做其他的工作*/
//从future对象中读取数据,会进行等待
double price = futurePrice.get();
Future中的异常处理
public Future<Double> getPriceAsync(String product) {
CompletableFuture<Double> futurePrice = new CompletableFuture<>();
new Thread( () -> {
try {
double price = calculatePrice(product);
futurePrice.complete(price);
} catch (Exception ex) {
//失败了,将异常放到future中,在获取时就会把异常抛出去
futurePrice.completeExceptionally(ex);
}
}).start();
return futurePrice;
}
使用工厂方法创建
public Future<Double> getPriceAsync(String product) {
return CompletableFuture.supplyAsync(() -> calculatePrice(product));
}
创建自定义的执行器
因为默认线程池的数目是固定的,因此可能效率会有问题,因此在某些情况下,需要创建自定义的执行器。
private final Executor executor = Executors.newFixedThreadPool(Math.min(shops.size(), 100),new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
});
CompletableFuture.supplyAsync(() -> shop.getName() + " price is " + shop.getPrice(product), executor);
多个异步任务进行流水线操作
public List<String> findPrices(String product) {
List<CompletableFuture<String>> priceFutures = shops.stream()
.map(shop -> CompletableFuture.supplyAsync(() -> shop.getPrice(product), executor))
//进行同步的操作
.map(future -> future.thenApply(Quote::parse))
//将上一个异步任务与下一个异步任务进行连接,流水线操作。
.map(future -> future.thenCompose(quote ->
CompletableFuture.supplyAsync(
() -> Discount.applyDiscount(quote), executor)))
.collect(toList());
return priceFutures.stream()
//取得返回值
.map(CompletableFuture::join)
.collect(toList());
}
其中:
thenCompose和前一个任务是在同一个线程中运行。
thenComposeAsync和前一个任务会将后续的任务提交到一个线程池,每个任务是由不同的线程处理的。
两个任务异步整合
//这里面相当是有三个CompletableFuture,前两个计算过后,由第三个进行整合。
Future<Double> futurePriceInUSD = CompletableFuture.supplyAsync(() -> shop.getPrice(product))
.thenCombine(CompletableFuture.supplyAsync(
() -> exchangeService.getRate(Money.EUR, Money.USD)),
(price, rate) -> price * rate
);
//其中thenCombineAsync是thenCombine的异步版本
处理完成后的异步任务流水线
//接收一个function来处理异步任务的返回值。
CompletableFuture[] futures = findPricesStream("myPhone").map(f -> f.thenAccept(System.out::println)).toArray(size -> new CompletableFuture[size]);
//接收一个数组,等所有的异步任务完成后,返回一个CompletableFuture<Void>对象。
CompletableFuture.allOf(futures).join();
//还有一个方法叫做antOf,类似于allof,不过他是只获取一个结果。