// 待实现
}
}
模拟1秒钟延迟的方法
public static void delay() {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
在getPrice方法中引入一个模拟的延迟
public double getPrice(String product) {
return calculatePrice(product);
}
private double calculatePrice(String product) {
delay();
return random.nextDouble() * product.charAt(0) + product.charAt(1);
}
将同步方法转换为异步方法
将getPrice转换为getPriceAsync方法,并修改它的返回值:
public Future getPriceAsync(String product) {
CompletableFuture futurePrice = new CompletableFuture<>();
new Thread( () -> {
double price = calculatePrice(product);
futurePrice.complete(price);
}).start();
//无需等待还没结束的计算,直接返回Future对象
return futurePrice;
}
使用异步API
运行结果
Invocation returned after 43 msecs
Price is 123.26
Price returned after 1045 msecs
错误处理
如果价格计算过程中产生了错误会怎样呢?非常不幸,这种情况下你会得到一个相当糟糕的结果:用于提示错误的异常会被限制在试图计算商品价格的当前线程的范围内,最终会杀死该线程,而这会导致等待get方法返回结果的客户端永久地被阻塞。
客户端可以使用重载版本的get方法,它使用一个超时参数来避免发生这样的情况。使用这种方法至少能防止程序永久地等待下去,超时发生时,程序会得到通知发生了TimeoutException。
为了让客户端能了解商店无法提供请求商品价格的原因,你需要使用CompletableFuture的completeExceptionally方法将导致CompletableFuture内发生问题的异常抛出。
public Future getPriceAsync(String product) {
CompletableFuture futurePrice = new CompletableFuture<>();
new Thread( () -> {
try {
double price = calculatePrice(product);
futurePrice.complete(price);
} catch (Exception ex) {
futurePrice.completeExceptionally(ex);
}
}).start();
return futurePrice;
}
使用工厂方法supplyAsync创建CompletableFuture
CompletableFuture类自身提供了大量精巧的工厂方法,使用这些方法能更容易地完成整个流程,还不用担心实现的细节。
public Future getPriceAsync(String product) {
return CompletableFuture.supplyAsync(() -> calculatePrice(product));
}
你已经被要求进行“最佳价格查询器”应用的开发了,不过你需要查询的所有商店只提供了同步API。
换句话说,你有一个商家的列表,如下所示:
List shops = Arrays.asList(new Shop(“BestPrice”),
new Shop(“LetsSaveBig”),
new Shop(“MyFavoriteShop”),
new Shop(“BuyItAll”));
采用顺序查询所有商店的方式实现的findPrices方法
public List findPrices(String product) {
return shops.stream()
.map(shop -> String.format(“%s