场景
以下是一个顾客下单的流程模拟:
1、获取基本产品信息(此处查询数据库)
2、获取每一个产品的价格(假设此处需要通过第三方服务平台进行实时定价,产品不同调用的平台亦不同,所有此处是挨个获取)
3、计算产品总价
4、获取用户余额(此处也是调取第三方服务,获取用户账户余额)
5、比对余额是否充足
6、如果余额充足则提示购买成功,并扣去花费,更新用户余额(此处也是调取第三方服务,更新用户账户余额)
7、返回是否购买成功
代码
public class App {
public static void main(String[] args) throws Exception {
App app = new App();
// 1. 非并发查询
app.searchProduct();
// 2. CompletableFuture 优化
app.searchProductByCompletableFuture();
}
public void searchProductByCompletableFuture() throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(5);
ExecutorService subExecutorService = Executors.newFixedThreadPool(5);
try {
long timeStart = System.currentTimeMillis();
CompletableFuture<List<Product>> listCompletableFuture = CompletableFuture.supplyAsync(() -> {
try {
// 1.获取基本产品信息
return getProducts();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}, executorService)
.whenComplete(new LogErrorAction<>("getProducts"))
.thenApply(productList -> {
// 2.并发获取每一个产品的价格
productList
.stream()
.forEach(product -> {
BigDecimal realPrice = CompletableFuture
.supplyAsync(() -> getProductPrice(product), subExecutorService)
.join();
product.setPrice(realPrice);
}
);
return productList;
});
//3.获取用户余额
CompletableFuture<BigDecimal> userAccountCf = CompletableFuture.supplyAsync(() -> {
try {
return getUserAccount();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}, executorService).whenComplete(new LogErrorAction<>("getUserAccount"));
// List<Product> allProduct = listCompletableFuture.join();
// 同步阻塞获取所有数据结果
CompletableFuture<Void> cf3 = CompletableFuture.allOf(userAccountCf, listCompletableFuture);
cf3.thenAccept(v -> {
//这里的join并不会阻塞,因为传给thenAccept的函数是在 cf 全部完成时,才会执行。
List<Product> allProduct = listCompletableFuture.join();
// 4、计算产品总价
BigDecimal priceSum = allProduct.stream()
.map(Product::getPrice)
.reduce(new BigDecimal(0), BigDecimal::add);
System.out.println("searchProductByCompletableFuture:产品总价:" + priceSum);
Assert.assertEquals("2780", priceSum.toString());
BigDecimal userAccount = userAccountCf.join();
// 5、比对余额是否充足
String result = "";
if (userAccount.compareTo(priceSum) < 0) {
result = "余额不足,购买失败";
} else {
result = "余额充足,购买成功";
// 6、更新用户的余额
BigDecimal left = userAccount.subtract(priceSum);
System.out.println("searchProductByCompletableFuture:用户购买后余额:" + left);
updateUserAccount(left);
}
System.out.println(result);
});
long timeUseMs = System.currentTimeMillis() - timeStart;
System.out.println("searchProductByCompletableFuture:并发查询耗时:" + timeUseMs);
} finally {
executorService.shutdown();
subExecutorService.shutdown();
}
}
public void searchProduct() throws InterruptedException {
long timeStart = System.currentTimeMillis();
// 1、获取基本产品信息
List<Product> productList = getProducts();
// 2、获取每一个产品的价格
for (Product product : productList) {
product.setPrice(getProductPrice(product));
}
// 3、计算产品总价
BigDecimal priceSum = productList.stream()
.map(Product::getPrice)
.reduce(new BigDecimal(0), BigDecimal::add);
System.out.println("searchProduct: 产品总价:" + priceSum);
Assert.assertEquals("2780", priceSum.toString());
// 4、获取用户余额
BigDecimal userAccount = getUserAccount();
// 5、比对余额是否充足
String result;
if (userAccount.compareTo(priceSum) < 0) {
result = "余额不足,购买失败";
} else {
result = "余额充足,购买成功";
// 6、更新用户的余额
BigDecimal left = userAccount.subtract(priceSum);
System.out.println("searchProduct: 用户购买后余额:" + left);
updateUserAccount(left);
}
System.out.println(result);
long timeUseMs = System.currentTimeMillis() - timeStart;
System.out.println("searchProduct: 非并发查询耗时:" + timeUseMs);
}
/**
* 获取产品价格,模拟调用外部服务
*
* @param product 产品
* @return 产品价格
* @throws InterruptedException Exception
*/
public BigDecimal getProductPrice(Product product) {
// 模拟耗时查询——调用外部服务接口
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new BigDecimal(product.getId() * 10 + 233);
}
/**
* 获取产品列表,模拟从数据库查询数据
*
* @return 产品列表
* @throws InterruptedException Exception
*/
public List<Product> getProducts() throws InterruptedException {
List<Product> productList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Product product = new Product();
product.setId((long) i);
product.setName("product" + i);
product.setCreateTime(new Date());
productList.add(product);
}
// 模拟耗时查询
Thread.sleep(1000);
return productList;
}
/**
* 获取用户的账户余额
*
* @return 账户余额
* @throws InterruptedException Exception
*/
public BigDecimal getUserAccount() throws InterruptedException {
// 模拟耗时查询 —— 调用外部服务获取当前用户余额
Thread.sleep(500);
return new BigDecimal(3000);
}
/**
* 更新用户的账户余额
*
* @param left 账户余额
* @throws InterruptedException Exception
*/
public boolean updateUserAccount(BigDecimal left) {
// 模拟耗时操作 —— 调用外部服务更新当前用户余额
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return true;
}
}