场景
工作中真实案例,有个接口执行比较慢,业务系统调用经常出现超时
改造:直接简单的换成异步处理,业务系统调用的时候先直接返回一个值,告诉业务系统已经成功的把数据推送到我系统这边来了,主要的业务处理,由异步线程去做,异步线程处理完后,在调用业务系统提供的接口把返回值下发回去。
伪代码
private void batchAddReceiveAsync(Request requestVo) {
CompletableFuture.runAsync(()->{
try {
//模拟处理业务
Thread.sleep(10000);
System.out.println("异步线程处理中");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println("main线程处理完毕");
}
这种方式偶尔会出现异步线程里面的代码没有执行。
测试结果:结果只输出了main线程处理完毕,异步线程的结果并没有输出,可见异步线程没有执行。
原因:默认主线程关闭太快导致自定义线程实例直接销毁 !
改造后的代码
private void batchAddReceiveAsync(FinBatchAddReceiveApplyAndReceivableVo requestVo) {
ExecutorService executor = ThreadUtil.newSingleExecutor();
try {
CompletableFuture.runAsync(() -> {
//模拟处理业务
Thread.sleep(10000);
System.out.println("异步线程处理中");
}, executor).whenComplete((reslut, e) -> {
SimpleReceiveApplyCallBackVO finReceiveApply = new SimpleReceiveApplyCallBackVO();
if (e != null) {
finReceiveApply.setIsError(Boolean.TRUE);
finReceiveApply.setErrorMsg(e.getMessage());
}
finReceiveApply.setSystemType(requestVo.getSystemType());
finReceiveApply.setBatchNo(requestVo.getBatchNo());
//下发回调给业务系统
feign.issued(finReceiveApply);
});
} catch (Exception e) {
log.error("新增接口出现错误:{}", e.getMessage());
} finally {
executor.shutdown();
}
}
测试成功,主线程和异步线程的消息均打印出来 !