在Java 8中, 新增加了一个包含50个方法左右的类: CompletableFuture,结合了Future的优点,提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,提供了函数式编程的能力,可以通过回调的方式处理计算结果,并且提供了转换和组合CompletableFuture的方法。
CompletableFuture被设计在Java中进行异步编程。异步编程意味着在主线程之外创建一个独立的线程,与主线程分隔开,并在上面运行一个非阻塞的任务,然后通知主线程进展,成功或者失败。
通过这种方式,你的主线程不用为了任务的完成而阻塞/等待,你可以用主线程去并行执行其他的任务。 使用这种并行方式,极大地提升了程序的表现。
译文:
当一个Future可能需要显示地完成时,使用CompletionStage接口去支持完成时触发的函数和操作。
当2个以上线程同时尝试完成、异常完成、取消一个CompletableFuture时,只有一个能成功。
CompletableFuture实现了CompletionStage接口的如下策略:
1.为了完成当前的CompletableFuture接口或者其他完成方法的回调函数的线程,提供了非异步的完成操作。
2.没有显式入参Executor的所有async方法都使用ForkJoinPool.commonPool()为了简化监视、调试和跟踪,
所有生成的异步任务都是标记接口AsynchronousCompletionTask的实例。
3.所有的CompletionStage方法都是独立于其他共有方法实现的,因此一个方法的行为不会受到子类中其他
方法的覆盖。
CompletableFuture实现了Futurre接口的如下策略:
1.CompletableFuture无法直接控制完成,所以cancel操作被视为是另一种异常完成形式。
方法isCompletedExceptionally可以用来确定一个CompletableFuture是否以任何异常的方式完成。
2.以一个CompletionException为例,方法get()和get(long,TimeUnit)抛出一个ExecutionException,
对应CompletionException。为了在大多数上下文中简化用法,这个类还定义了方法join()和getNow,
而不是直接在这些情况中直接抛出CompletionException。
简单小案例:
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture aFuture = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("a人员数钱完毕");
return 100;
});
CompletableFuture bFuture = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(4000);
System.out.println("b人员数钱完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}
return 300;
});
CompletableFuture cFuture = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
System.out.println("c人员数钱完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}
return 300;
});
System.out.println("开始..." + new Date().toLocaleString());
//并行处理
CompletableFuture.allOf(aFuture, bFuture, cFuture).join();
//取值
Integer a = aFuture.get();
Integer b = bFuture.get();
Integer c = cFuture.get();
System.out.println(a + b + c);
System.out.println("结束..." + new Date().toLocaleString());
}
实战:
//未优化前代码
@Override
public IndexBaseInfoVO getBaseInfo(String beginCreateTime, String endCreateTime) {
//1)构建一个空的结果集对象
IndexBaseInfoVO result = new IndexBaseInfoVO();
//2 封装结果集属性
// 2.1 由于查询需要用到用户名 调用工具类获取用户名
String username = SecurityUtils.getUsername();
try {
//3 封装结果集对象
result.setCluesNum(reportMpper.getCluesNum(beginCreateTime, endCreateTime, username));
result.setBusinessNum(reportMpper.getBusinessNum(beginCreateTime, endCreateTime, username));
result.setContractNum(reportMpper.getContractNum(beginCreateTime, endCreateTime, username));
result.setSalesAmount(reportMpper.getSalesAmount(beginCreateTime, endCreateTime, username));
} catch (Exception e) {
e.printStackTrace();
return null;
}
//4 返回结果集对象
return result;
优化后代码:
/*---------------------------------首页基本数据--使用CompletableFuture 技术优化--------------------------------------*/
@Override
public IndexBaseInfoVO getBaseInfo(String beginCreateTime, String endCreateTime) {
//1)构建一个空的结果集对象
IndexBaseInfoVO result = new IndexBaseInfoVO();
//2 封装结果集属性
// 2.1 由于查询需要用到用户名 调用工具类获取用户名
String username = SecurityUtils.getUsername();
try {
CompletableFuture cluesNums = CompletableFuture.supplyAsync(() -> {
//线索数量
return reportMpper.getCluesNum(beginCreateTime, endCreateTime, username);
});
CompletableFuture businessNum = CompletableFuture.supplyAsync(() -> {
//商机数量
return reportMpper.getBusinessNum(beginCreateTime, endCreateTime, username);
});
CompletableFuture contractNum = CompletableFuture.supplyAsync(() -> {
//合同数量
return reportMpper.getContractNum(beginCreateTime, endCreateTime, username);
});
CompletableFuture salesAmount = CompletableFuture.supplyAsync(() -> {
//销售金额
return reportMpper.getSalesAmount(beginCreateTime, endCreateTime, username);
});
//3. join等待所有线程全部执行完成
CompletableFuture.
allOf(
cluesNums,
businessNum,
contractNum,
salesAmount)
.join();
//4.封装结果集对象
result.setCluesNum(cluesNums.get());
result.setBusinessNum(businessNum.get());
result.setContractNum(contractNum.get());
result.setSalesAmount(salesAmount.get());
} catch (Exception e) {
e.printStackTrace();
}
//5 返回结果集对象
return result;
}
/*-------------------------------------------代码优化完毕----------------------------------------------------------*/