本文带你快速了解@Async注解的用法,包括异步方法无返回值、有返回值,最后总结了@Async注解失效的几个坑。
在 SpringBoot 应用中,经常会遇到在一个接口中,同时做事情1,事情2,事情3,如果同步执行的话,则本次接口时间取决于事情1 2 3执行时间之和;如果三件事同时执行,则本次接口时间取决于事情1 2 3执行时间最长的那个,合理使用多线程,可以大大缩短接口时间。那么在 SpringBoot 应用中如何优雅的使用多线程呢?
(相关资料图)
Don"t bb, show me code.
SpringBoot应用中需要添加@EnableAsync
注解,来开启异步调用,一般还会配置一个线程池,异步的方法交给特定的线程池完成,如下:
@Configuration@EnableAsyncpublic class AsyncConfiguration { @Bean("doSomethingExecutor") public Executor doSomethingExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // 核心线程数:线程池创建时候初始化的线程数 executor.setCorePoolSize(10); // 最大线程数:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程 executor.setMaxPoolSize(20); // 缓冲队列:用来缓冲执行任务的队列 executor.setQueueCapacity(500); // 允许线程的空闲时间60秒:当超过了核心线程之外的线程在空闲时间到达之后会被销毁 executor.setKeepAliveSeconds(60); // 线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池 executor.setThreadNamePrefix("do-something-"); // 缓冲队列满了之后的拒绝策略:由调用线程处理(一般是主线程) executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); executor.initialize(); return executor; }}
使用的方式非常简单,在需要异步的方法上加@Async
注解
@RestControllerpublic class AsyncController { @Autowired private AsyncService asyncService; @GetMapping("/open/something") public String something() { int count = 10; for (int i = 0; i < count; i++) { asyncService.doSomething("index = " + i); } lon return "success"; }}@Slf4j@Servicepublic class AsyncService { // 指定使用beanname为doSomethingExecutor的线程池 @Async("doSomethingExecutor") public String doSomething(String message) { log.info("do something, message={}", message); try { Thread.sleep(1000); } catch (InterruptedException e) { log.error("do something error: ", e); } return message; }}
访问:127.0.0.1:8080/open/something,日志如下
2020-04-19 23:42:42.486 INFO 21168 --- [io-8200-exec-17] x.g.b.system.controller.AsyncController : do something end, time 8 milliseconds2020-04-19 23:42:42.488 INFO 21168 --- [ do-something-1] x.gits.boot.system.service.AsyncService : do something, message=index = 02020-04-19 23:42:42.488 INFO 21168 --- [ do-something-5] x.gits.boot.system.service.AsyncService : do something, message=index = 42020-04-19 23:42:42.488 INFO 21168 --- [ do-something-4] x.gits.boot.system.service.AsyncService : do something, message=index = 32020-04-19 23:42:42.488 INFO 21168 --- [ do-something-6] x.gits.boot.system.service.AsyncService : do something, message=index = 52020-04-19 23:42:42.488 INFO 21168 --- [ do-something-9] x.gits.boot.system.service.AsyncService : do something, message=index = 82020-04-19 23:42:42.488 INFO 21168 --- [ do-something-8] x.gits.boot.system.service.AsyncService : do something, message=index = 72020-04-19 23:42:42.488 INFO 21168 --- [do-something-10] x.gits.boot.system.service.AsyncService : do something, message=index = 92020-04-19 23:42:42.488 INFO 21168 --- [ do-something-7] x.gits.boot.system.service.AsyncService : do something, message=index = 62020-04-19 23:42:42.488 INFO 21168 --- [ do-something-2] x.gits.boot.system.service.AsyncService : do something, message=index = 12020-04-19 23:42:42.488 INFO 21168 --- [ do-something-3] x.gits.boot.system.service.AsyncService : do something, message=index = 2
由此可见已经达到异步执行的效果了,并且使用到了咱们配置的线程池。
当异步方法有返回值时,如何获取异步方法执行的返回结果呢?这时需要异步调用的方法带有返回值CompletableFuture。
CompletableFuture是对Feature的增强,Feature只能处理简单的异步任务,而CompletableFuture可以将多个异步任务进行复杂的组合。如下:
@RestControllerpublic class AsyncController { @Autowired private AsyncService asyncService; @SneakyThrows @ApiOperation("异步 有返回值") @GetMapping("/open/somethings") public String somethings() { CompletableFuture createOrder = asyncService.doSomething1("create order"); CompletableFuture reduceAccount = asyncService.doSomething2("reduce account"); CompletableFuture saveLog = asyncService.doSomething3("save log"); // 等待所有任务都执行完 CompletableFuture.allOf(createOrder, reduceAccount, saveLog).join(); // 获取每个任务的返回结果 String result = createOrder.get() + reduceAccount.get() + saveLog.get(); return result; }}@Slf4j@Servicepublic class AsyncService { @Async("doSomethingExecutor") public CompletableFuture doSomething1(String message) throws InterruptedException { log.info("do something1: {}", message); Thread.sleep(1000); return CompletableFuture.completedFuture("do something1: " + message); } @Async("doSomethingExecutor") public CompletableFuture doSomething2(String message) throws InterruptedException { log.info("do something2: {}", message); Thread.sleep(1000); return CompletableFuture.completedFuture("; do something2: " + message); } @Async("doSomethingExecutor") public CompletableFuture doSomething3(String message) throws InterruptedException { log.info("do something3: {}", message); Thread.sleep(1000); return CompletableFuture.completedFuture("; do something3: " + message); }}
访问接口
C:\Users\Administrator>curl -X GET "http://localhost:8200/open/somethings" -H "accept: */*"do something1: create order; do something2: reduce account; do something3: save log
控制台上关键日志如下:
2020-04-20 00:27:42.238 INFO 5672 --- [ do-something-3] x.gits.boot.system.service.AsyncService : do something3: save log2020-04-20 00:27:42.238 INFO 5672 --- [ do-something-2] x.gits.boot.system.service.AsyncService : do something2: reduce account2020-04-20 00:27:42.238 INFO 5672 --- [ do-something-1] x.gits.boot.system.service.AsyncService : do something1: create order
@Async
注解会在以下几个场景失效,也就是说明明使用了@Async
注解,但就没有走多线程。
@Component
和@Service
,并且能被Spring扫描到);SpringBoot应用中没有添加@EnableAsync
注解;在同一个类中,一个方法调用另外一个有@Async注解的方法,注解不会生效。原因是@Async注解的方法,是在代理类中执行的。通过上边几个示例,@Async实际还是通过Future或CompletableFuture来异步执行的,Spring又封装了一下,让我们使用的更方便。
在SpringBoot应用中,经常会遇到在一个接口中,同时做事情1,事情2,事情3,如果同步执行的话,则本次接口时间取决于事情123执行时间之和;如果三
本周,A股市场整体呈沪强深弱的态势。这样的市况中,机构研究员的动向又是怎么样的呢?据投资快报投研通数据统计,本周券商研究员对113家公司的
3月17日,新诺威披露2022年度业绩报告。数据显示,新诺威去年实现营业收入26 26亿元,同比增长42%,实现归属于上市公司股东的净利润7 26亿元,
1、有两种方法:当输入乘号的时候,把输入中文模式改为英文模式。2、然后点击一下X键到光标处,再将英文模式改为中文模式。3
1、收缩毛孔的方法一:小苏打每次清洁脸部时,把小苏打混合洗面奶充分打起泡泡,这个时候你会发现泡泡变得非常细腻,涂抹在脸
3月14日,中国驻斯洛伐克大使孙立杰、商务参赞王宏亮一行到软控欧洲研发中心考察调研。 软控股份董事长兼总裁官炳政等公司领导热情迎接来访
2023年3月17日博士眼镜(300622)发布公告称公司于2023年3月13日接受机构调研,安联基金、嘉实基金、民加基金、太平基金、泰达宏利、泰康资产
中国商务新闻网是商务部国际商报社主办,国家互联网信息办公室批准的国家一类新闻网站,是全国商务系统网络宣传和信息服务的重要窗口,是我国
山西证券股份有限公司陈振志,周蓉近期对顺鑫农业进行研究并发布了研究报告《坚定聚焦白酒猪肉业务,产品结构升级打开新篇章》,本报告对顺鑫农
1、热力学第零定律于1930年由福勒(R H Fowler)正式提出,比热力学第一定律和热力学第二定律晚了80余年。2、
近日,一组中外科学家研究团队通过计算机断层扫描分析表明,在中国发现的一个马门溪龙标本的颈部长度达15米,比长颈鹿的脖子长6倍。据科学家称
中国商务新闻网是商务部国际商报社主办,国家互联网信息办公室批准的国家一类新闻网站,是全国商务系统网络宣传和信息服务的重要窗口,是我国
中国商务新闻网是商务部国际商报社主办,国家互联网信息办公室批准的国家一类新闻网站,是全国商务系统网络宣传和信息服务的重要窗口,是我国
中国商务新闻网是商务部国际商报社主办,国家互联网信息办公室批准的国家一类新闻网站,是全国商务系统网络宣传和信息服务的重要窗口,是我国
中国商务新闻网是商务部国际商报社主办,国家互联网信息办公室批准的国家一类新闻网站,是全国商务系统网络宣传和信息服务的重要窗口,是我国
中国商务新闻网是商务部国际商报社主办,国家互联网信息办公室批准的国家一类新闻网站,是全国商务系统网络宣传和信息服务的重要窗口,是我国
山东地区加氢苯市场主流报价区间在6950~7000元 吨,均价6975元 吨,较上一交易日下调50元 吨。纯苯价格:京博石化报价7200元 吨,汇丰石化报价72
产品3月16日3月17日涨跌幅单位:元 吨OX850085000元 吨苯酐870087000元 吨DOP10000101000 1%元 吨3月17日苯酐市场价格
3月17日,利华益利津炼化有限公司工业硫磺报价1240元 吨,液体硫磺报价1240元 吨,3月14日企业调价,价格下调30元 吨,目前硫磺市场观望为主,
3月17日,山东万华化学苯乙烯65万吨 年新装置正常产销,目前销售华北地区8600元 吨,华东地区8600元 吨,国际油价反弹,成本支撑较好,但苯乙
为进一步增强金融消费者自我权益保护意识,成都银行以“共筑诚信消费环境、提振金融消费信心”为主题,聚焦“一老一少一新”等重点群体,在立
3月16日,柏睿数据在北京举办“数智引领睿创新机——柏睿数据2023新品发布媒体见面会”,全面升级未来数据智能战略,发布全新数据智能产品矩阵
3月10日,南京市秦淮区人社局领导一行莅临云生集团走访交流。秦淮区人力资源和社会保障局副局长苏瑞中、人力资源管理科科长雷廷、秦淮区新管
3月17日,山东华鲁恒升集团异辛醇装置运行正常。出厂价格9500元 吨,报价上涨,涨幅100元 吨,实际成交价以协商为主。上游丙烯行情小幅上涨,
江苏东成生物科技15万吨 年木薯普级乙醇装置停机,企业普级对外报价下调50元 吨报6750元 吨。河南汉永酒精有限公司30万吨 年乙醇装置正常,优
如何抓好今冬明春市场监管领域安全生
12月16日,达州市达川区市场监督管理局下发《市场监管领域今冬明春安全生产隐患大排查大整治行动工作方案》,要求下属各部门从2022年12月16日起至2023年3月15日,全面聚焦城镇燃气、特种设备、危险化学品、烟花爆
《2021年度中国对外直接投资统计公报
金港高速公路连接柬埔寨首都金边和该国最大深水海港西哈努克港,是中国路桥按建造—运营—移交模式投资的项目,采用中国设计及质量标准,横跨5个省份,全长187 05公里,双向四车道。金港高速公路通车后,从金边到
总体保持稳定恢复态势 工业经济展现
2022年1至10月,浙江省宁波市811家汽车制造业规上工业总产值2646 8亿元,同比增长14 2%。图为11月19日,工人在领克汽车宁波梅山工厂的总装车间作业。今年以来,受疫情多发散发、市场需求不振等因素影响,国内工业
14家券商获首批个人养老金代销展业资
11月18日晚间,证监会发布《个人养老金基金销售机构名录》,共37家机构入围,其中券商14家,银行16家,独立基金销售机构7家。14家券商包括华泰证券、中信证券、海通证券、国泰君安、申万宏源、中金财富和长江证券
北京再担保承保规模超6000亿 覆盖中
北京中小企业融资再担保有限公司(简称北京再担保)发布的最新数据显示,成立14年来已累计承保规模超过6000亿元,覆盖中小微企业(农户)超过16万户次,积极推动北京市中小微企业融资规模不断扩大。北京再担保2008年
Copyright @ 2001-2023 www.u74.cn All Rights Reserved 商业时报网 版权所有
网站信息内容, 均为相关单位具有著作权,未经书面授权,转载注明出处
未经商业时报网书面授权,请勿建立镜像,转载请注明来源,违者依法必究