记一次CompletableFuture.supplyAsync 的使用遇到的问题
背景: 平时我们的接口方法响应不会时间太长,nginx或者后端框架都会有默认接口响应时间,超时后熔断,返回默认值,或者默认错误的设置。
需求: 千万级的表数据关联,要求按一些纬度分组后求值,推送至第三方系统,要求是前端点按钮触发,这里防重机制后面再说。
-
开发:
查询性能优化索引查询语句等后,从三分多钟优化到一分40秒,接口正常,前端仍然pending过后,404熔断,这样级别调高响应时间也不是长久之计,于是改为异步执行,接口直接返回结果。
于是找到了CompletableFuture.supplyAsync(x->())这个方法,如下写完后,死活进不了异步方法里面:
` @RestController @RequestMapping(value = "/task") public class SyncTask { @PostMapping(value = "/sync") public String testSync() throws InterruptedException {
// 开启异步任务执行任务
CompletableFuture<String> future = CompletableFuture.supplyAsync(() ->
{
try {
System.out.println("我进到异步方法里面了=======================");
this.sync();
} catch (InterruptedException e) {
e.printStackTrace();
}
return "耗时任务完成";
}
);
try {
// 必须在future.complete之前sleep 异步线程才能执行
// Thread.sleep(200); future.complete("执行成功!"); // 这里直接返回前端结果 ,这里sleep无效 Thread.sleep(2000); return future.get(); } catch (ExecutionException e) { e.printStackTrace(); } finally { // do nothing } // 这里主线程不休眠的话,异步线程池会秒结束,这个不知道什么机制,需要研究一下,这里sleep无效 // Thread.sleep(2000); return "方法结束"; }
/**
* 这是一个非常非常耗时的接口方法
*
* [@return](https://my.oschina.net/u/556800)
* [@throws](https://my.oschina.net/throws) InterruptedException
*/
private String sync() throws InterruptedException {
System.out.println("执行到耗时方法了!");
Thread.sleep(1000 * 10);
return "success";
}
}`
然后,找demo看大家都怎么用的,很多使用里面都写了这么句话
/* // 主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭: */
于是,我就在主线程中加了sleep方法,让主线程先休眠。无效。
最后,最后, 我在 future.complete("执行成功!"); 执行前进行sleep(),问题就得到了解决。
虽然还不知道是什么机制,但问题暂时是解决了,等我分析完原理,在贴在这个博客里,特此记录。
来源:oschina
链接:https://my.oschina.net/xiaomingnevermind/blog/4937923