CompletableFuture的实际使用

1、首先我们经常听说java 8 新增了CompletableFuture,但是不是所有人都是有机会来使用的

2、业务逻辑是把大量文件转发到各个系统

思路:

1、需要通过@Async("taskExecutor")注解来实现点击之后的异步操作

2、通过需要转发系统的数量来创建对应线程池中的数量

3、具体异步操作是CompletableFuture实现的,通过循环需要转发不同系统,来记录是否转发成功状态以及相关信息、以及相关业务

4、最后关闭线程池

3、直接上代码,我用的是带有返回值的异步


//创建应用数量的线程池
ExecutorService service = Executors.newFixedThreadPool(appList.size());


//2 创建应用列表数量的CompletableFuture 线程处理每个应用的文件转发
for (XmAppRegister app : appList) {
CompletableFuture.supplyAsync(() -> {
for (BizArticle article : articleList) {
if (StringUtils.isEmpty(app.getAppId())) {
return ResultUtils.success(ErrorCode.GENERAL, "应用id不能为空", null);
}
if (Objects.isNull(article.getId())) {
return ResultUtils.success(ErrorCode.GENERAL, "文件id不能为空", null);
}
XmFileApp xfa = xmFileAppMapper.selectByFileApp(jobId, app.getAppId(), article.getId());
//更新分发中状态
xfa.setExecStatus("分发中");
xmFileAppMapper.updateByPrimaryKeySelective(xfa);
//请求路径
String reqPath = app.getFileTransPath();
//文件真实路径
String fullPath = WaveConstants.BASE_PATH + article.getRelativePath();
log.info("开始文件上传");
//3 读取不同文件来进行文件转发
JSONObject retMap = FileUtils.upload(reqPath, fullPath, UUID.randomUUID().toString());
log.info("文件上传返回{}", retMap);
XmForwardLog forwardLog = new XmForwardLog();
String param = StringUtils.substringAfterLast(fullPath, WaveConstants.SEPARATE);
//对方系统返回数据
if (!retMap.isEmpty()) {
//判断目标系统接口状态码是否异常
String httpCode = String.valueOf(retMap.getInteger("code"));
//2开头都是正常状态码
if (httpCode.startsWith("2")) {
xfa.setExecStatus("分发成功");
} else {
xfa.setExecStatus("分发失败");
}
if (StringUtils.isEmpty(httpCode)) {
httpCode = "无响应码";
}
String msg = retMap.getString("msg");
if (StringUtils.isEmpty(msg)) {
msg = "无任何响应内容";
}
forwardLog = XmForwardLog.of(xfa.getFaId(), reqPath, param,
httpCode, msg);
} else {
xfa.setExecStatus("分发失败");
forwardLog = XmForwardLog.of(xfa.getFaId(), reqPath, param,
"无响应码", "无任何响应内容");
}
//4 合并应用信息\文件转发状态
xmFileAppMapper.updateByPrimaryKeySelective(xfa);
xmForwardLogMapper.insert(forwardLog);
}
return null;
}, service)
.exceptionally((e) -> {
e.printStackTrace();
return ResultUtils.success(ErrorCode.GENERAL.getCode(), "系统错误", null);
});
}

//关闭线程池
service.shutdown();

4、总结

当时我拿到这个需求的时候,我对CompletableFuture是早有耳闻的,不过我之前基本没写多线程相关代码,晚上研究了一下之后,第二天开始写代码,其实在我看来还挺简单的

ps:如果遇到复杂的业务流程一定要先写好注释,再实现代码(这是我在项目中另外一个需求遇到的)

原文地址:https://www.cnblogs.com/quliang/p/15737013.html