一:前言
首先使用多线程来处理,比较慢的数据这个在平常的业务是非常见的,但是有些场景比较复杂,我们如果使用多线程去处理的话,是不知道,异步代码里面的逻辑什么时候走完的,这时候就需要用到线程的异步了
二:异步回调实现
CallServiceImpl.log.info("开始进入异步代码----------------");
//这里需要注意的是,如果你服务器核心数比较少的话,这里每次请求都会单独开一个线程,如果频繁调用的话容易导致CPU飙升,导致服务挂掉
ExecutorService executorService = Executors.newSingleThreadExecutor();
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
//这个一定要用try catch包裹住你的业务代码,不然如果线上报错的话是没办法捕获到异常的,方便生产环境排查问题
CallServiceImpl.log.info("开启异步" + Thread.currentThread().getName());
if (CollectionUtil.isNotEmpty(callTemporaryEntityList)) {
//分片插入
int count = (int) Math.ceil(callTemporaryEntityList.size() / 500.0);
if (count == 1) {
try {
callTemporaryMapper.batchInsertCallTemp(database, callTemporaryEntityList);
} catch (Exception e) {
e.printStackTrace();
}
} else {
List<List<CallTemporaryEntity>> listPartition = Lists.partition(callTemporaryEntityList, count);
// 分片批量插入
for (List<CallTemporaryEntity> item : listPartition) {
try {
callTemporaryMapper.batchInsertCallTemp(database, item);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return "批量插入数据成功";
}, executorService).thenApply((result) -> {
CallServiceImpl.log.info("异步任务执行完成,获取到结果" + result);
//异步回调的结果,可以是一个对象也个事一个字符串
//修改状态为待解析
try {
customerFileMapper.updateFileStatusAndInvalidCount(database, id, 1, invalidPhoneCount);
} catch (Exception e) {
e.printStackTrace();
}
CallServiceImpl.log.info("异步任务执行完成,修改文件状态:{}", id);
executorService.shutdown();
return "修改文件状态成功";
});
三:总结
我觉得多线程的异步对于一些特殊需要回调的场景是非常有用的,所以这里记录一下,另外有一句话就是不懂线程池回调,就不要说自己精通并发哈哈!