SpringBoot @Async 注解无效
发布日期:2021-06-30 12:36:57
浏览次数:3
分类:技术文章
本文共 3868 字,大约阅读时间需要 12 分钟。
开发环境
- SpringBoot 2.1.10.RELEASE
- JDK 1.8
场景
在一个类的方法中,调用同类的异步方法无效,例如以下示例:
package com.nobody.controller;import java.util.concurrent.TimeUnit;import org.springframework.scheduling.annotation.Async;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("demo")public class DemoController { @GetMapping("test") public void test() { asyncTask(); System.out.println("主线程 Thread name:" + Thread.currentThread().getName()); } @Async public void asyncTask() { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("异步方法 Thread name:" + Thread.currentThread().getName()); }}
启动类也添加@EnableAsync
注解
package com.nobody;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.scheduling.annotation.EnableAsync;@SpringBootApplication@EnableAsyncpublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }}
输出结果:
异步方法 Thread name:http-nio-9563-exec-1主线程 Thread name:http-nio-9563-exec-1
从结果分析,明显是串行单线程执行。
原因分析
类内部方法调用时,直接进行内部调用,没有走Spring的代理类。Async注解的实现都是基于Spring的AOP,而AOP的实现是基于动态代理模式实现的。调用方法的是对象本身而不是代理对象,没有经过Spring容器。
解决方案
新建一个类,通过注解让Spring容器管理,然后在调用类中注入对象。
package com.nobody.domain;import java.util.concurrent.TimeUnit;import org.springframework.scheduling.annotation.Async;import org.springframework.stereotype.Service;@Servicepublic class AsyncService { @Async public void asyncTask() { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("异步方法 Thread name:" + Thread.currentThread().getName()); }}
package com.nobody.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import com.nobody.domain.AsyncService;@RestController@RequestMapping("demo")public class DemoController { @Autowired private AsyncService asyncService; @GetMapping("test") public void test() { asyncService.asyncTask(); System.out.println("主线程 Thread name:" + Thread.currentThread().getName()); }}
输出结果:
主线程 Thread name:http-nio-9563-exec-1异步方法 Thread name:task-1
如果异步方法非要写在同一个类中,可以懒加载注入本类的实例,进行调用,例如:
package com.nobody.controller;import java.util.concurrent.TimeUnit;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Lazy;import org.springframework.scheduling.annotation.Async;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("demo")public class DemoController { @Autowired @Lazy // 懒加载注入,不加会报错 private DemoController demoController; @GetMapping("test") public void test() { // 通过DemoController实例调用 demoController.asyncTask(); System.out.println("主线程 Thread name:" + Thread.currentThread().getName()); } // 方法不能是private类型,不然还是串行单线程执行 @Async public void asyncTask() { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("异步方法 Thread name:" + Thread.currentThread().getName()); }}
输出结果:
主线程 Thread name:http-nio-9563-exec-1异步方法 Thread name:task-1
转载地址:https://javalib.blog.csdn.net/article/details/106276893 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
很好
[***.229.124.182]2024年04月13日 20时40分46秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
考研比惨五大专业排行榜,第一名没人不服!
2019-05-01
没钱没公司,怎么做一款付费产品
2019-05-01
Python 3.8 新特性来袭
2019-05-01
查询亿级数据毫秒级返回!Elasticsearch 是如何做到的?
2019-05-01
FastAPI 构建 API 服务,究竟有多快?
2019-05-01
为什么Quora选择用Python语言?
2019-05-01
一劳永逸学编程的方法
2019-05-01
代码整洁之道-编写 Pythonic 代码
2019-05-01
树莓派程序开机自启动
2019-05-01
连锁门店无线通信方案
2019-05-01
配置Lotus Domino集群视频详解
2019-05-01
OSSIM(开源安全信息管理系统)在企业网络管理中的应用
2019-05-01
如何搭建Eclipse +Apache Tomcat配置Java开发环境
2019-05-01
Linux软件万花筒
2019-05-01
《Linux企业应用案例精解》一书已由清华大学出版社出版
2019-05-01
安装配置FreeBSD9全过程体验
2019-05-01
全球开源软件发展趋势分析
2019-05-01
Linux系统安全加固(一)
2019-05-01
Linux常用的安全工具
2019-05-01