@Async失效之谜
@Async如何使用
- 异步的方法上加上@Async异步注解
- 启动类中需要加上@EnableAsync才有效
使用时类似于下列函数:
new Thread(()-> System.out.println("hello world !"))
@Async线程池
- 默认线程池
无论重复多少次,都默认8个左右的线程在跑
异步线程:task-1执行成功
异步线程:task-2执行成功
异步线程:task-3执行成功
异步线程:task-4执行成功
异步线程:task-5执行成功
异步线程:task-6执行成功
异步线程:task-7执行成功
异步线程:task-1执行成功
异步线程:task-2执行成功
异步线程:task-8执行成功
异步线程:task-3执行成功
异步线程:task-8执行成功
异步线程:task-6执行成功
异步线程:task-8执行成功
异步线程:task-5执行成功
异步线程:task-3执行成功
异步线程:task-2执行成功
异步线程:task-1执行成功 - 自定义线程池配置
/**
* 为Async配置自定义线程池
* 可存放的最多线程数为:MAX_POOL_SIZE+QUEUE_CAPACITY,同时进入线程池的数量超过这个就会报错
* 线程名称最多为MAX_POOL_SIZE个
*/
@Configuration
public class MyTaskExecutorConfig implements AsyncConfigurer {
/**
* 设置ThreadPoolExecutor的核心池大小。
*/
private static final int CORE_POOL_SIZE = 2;
/**
* 设置ThreadPoolExecutor的最大池大小。
*/
private static final int MAX_POOL_SIZE = 3;
/**
* 设置ThreadPoolExecutor的BlockingQueue的容量。
*/
private static final int QUEUE_CAPACITY = 5;
/**
* 配置类实现AsyncConfigurer接口并重写getAsyncExcutor方法,并返回一个ThreadPoolTaskExevutor
* 这样我们就获得了一个基于线程池的TaskExecutor
*/
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(CORE_POOL_SIZE);
taskExecutor.setMaxPoolSize(MAX_POOL_SIZE);
taskExecutor.setQueueCapacity(QUEUE_CAPACITY);
taskExecutor.initialize();
return taskExecutor;
}
}
异步线程:ThreadPoolTaskExecutor-2执行成功
异步线程:ThreadPoolTaskExecutor-1执行成功
异步线程:ThreadPoolTaskExecutor-3执行成功
异步线程:ThreadPoolTaskExecutor-1执行成功
异步线程:ThreadPoolTaskExecutor-3执行成功
异步线程:ThreadPoolTaskExecutor-2执行成功
异步线程:ThreadPoolTaskExecutor-1执行成功
异步线程:ThreadPoolTaskExecutor-3执行成功
@Async和@Controller同时使用存在异常
AbstractHandlerMethodMapping初始bean时,在afterPropertiesSet方法中initHandlerMethods()关联我们的SpringMVCBean
// 类型判断
if (beanType != null && isHandler(beanType)) {
// url处理
detectHandlerMethods(beanName);
}
// Controller和RequestMapping注解判断
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
a、@Controller不使用@Async注解时
@RestController
@Slf4j
public class MemberServiceImpl1 {
@GetMapping("/addUser1")
public String addUser() {
log.info(">>>流程1");
log.info(">>>流程2");
return "success";
}
}

b、@Controller使用@Async注解,但不继承接口时,异步失效
@RestController
@Slf4j
public class MemberServiceImpl3 {
@GetMapping("/addUser3")
public String addUser() {
log.info(">>>流程1");
addUserLog();
log.info(">>>流程3");
return "success";
}
@Async()
public String addUserLog() {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
log.info(">>>流程2");
return "success";
}
}


c、@Controller使用@Async注解,同时继承接口
@RestController
@Slf4j
public class MemberServiceImpl4 implements MemberService {
@Override
@GetMapping("/addUser4")
public String addUser() {
log.info(">>>流程1");
addUserLog();
log.info(">>>流程3");
return "success";
}
@Async()
public String addUserLog() {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
log.info(">>>流程2");
return "success";
}
}


@Async使用建议
- a、异步执行的建议单独开启一个类实现,或者从容器中直接获取到该代理类后执行
/**
* 异步代码写到别的地方,不要和Controller注解同时使用
*/
@RestController
@Slf4j
public class ResolveServiceImpl {
@Autowired
private MemberServiceManage memberServiceManage;
@GetMapping("/resolve2")
public String addUser() {
log.info(">>>流程1");
memberServiceManage.addUserLog();
log.info(">>>流程3");
return "success";
}
}
@Component
@Slf4j
public class MemberServiceManage {
@Async
public String addUserLog() {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
log.info(">>>流程2");
return "success";
}
}
/**
* 使用SpringUtils获得bean后调用,不要使用this操作
*/
@RestController
@Slf4j
public class ResolveServiceImpl {
@GetMapping("/resolve1")
public String addUser() {
log.info(">>>流程1");
//把直接调用改为从容器中取一次
ResolveServiceImpl bean = SpringUtils.getBean(ResolveServiceImpl.class);
bean.addUserLog();
log.info(">>>流程3");
return "success";
}
@Async()
public String addUserLog() {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
log.info(">>>流程2");
return "success";
}
}
- b、异步的方法上不要加static,加了static就不走AOP了
@Async失效之谜的更多相关文章
- springboot2.0 如何异步操作,@Async失效,无法进入异步
springboot异步操作可以使用@EnableAsync和@Async两个注解,本质就是多线程和动态代理. 一.配置一个线程池 @Configuration @EnableAsync//开启异步 ...
- Spring AOP失效之谜
每天学习一点点 编程PDF电子书免费下载: http://www.shitanlife.com/code 什么是AOP1 AOP(Aspect Oriented Programming),即面向切面编 ...
- Spring aop注解失效
问题 在spring 中使用 @Transactional . @Cacheable 或 自定义 AOP 注解时,对象内部方法中调用该对象的其他使用aop机制的方法会失效. @Transactiona ...
- SpringBoot线程池的创建、@Async配置步骤及注意事项
最近在做订单模块,用户购买服务类产品之后,需要进行预约,预约成功之后分别给商家和用户发送提醒短信.考虑发短信耗时的情况所以我想用异步的方法去执行,于是就在网上看见了Spring的@Async了. 但是 ...
- 关于AOP无法切入同类调用方法的问题
一.前言 Spring AOP在使用过程中需要注意一些问题,也就是平时我们说的陷阱,这些陷阱的出现是由于Spring AOP的实现方式造成的.每一样技术都或多或少有它的局限性,很难称得上完美,只要掌握 ...
- Java开发技术
1.基础技术 数据结构与算法 逻辑结构:数据对象中的数据元素之间的逻辑关系 1.集合结构:集合结构中的数据元素除了同属一个集合外,没有其他关系. 2.线性结构:线性结构中的数据元素之间是一对一的关 ...
- 如何在Spring异步调用中传递上下文
以下文章来源于aoho求索 ,作者aoho 1. 什么是异步调用? 异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步 ...
- 关于Spring注解@Async引发其他注解失效
概述 在前面一篇文章中,介绍,在一个Bean中注入自己,如果有@Async和@Transaction,如果使用@Autowire注入自身,会报循环依赖,如果使用BeanFactoryAware注入自己 ...
- 在同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational)的方法,注解失效的原因和解决方法
参考原贴地址:https://blog.csdn.net/clementad/article/details/47339519 在同一个类中,一个方法调用另外一个有注解(比如@Async,@Trans ...
随机推荐
- 【转】Setting up SDL Extension Libraries on Visual Studio 2019 Community
FROM:http://lazyfoo.net/tutorials/SDL/06_extension_libraries_and_loading_other_image_formats/windows ...
- Java技术平台介绍
Java的名字的来源:Java是印度尼西亚爪哇岛的英文名称,因盛产咖啡而闻名.Java语言中的许多库类名称,多与咖啡有关, 如JavaBeans(咖啡豆).NetBeans(网络豆)以及ObjectB ...
- HTTP协议(2)
HTTP协议主要是有HTTP请求报文和HTTP响应报文组成的. HTTP请求报文主要分为四个部分: 第一部分:请求行.独占一行,由请求方法.请求url以及协议/版本组成: 第二部分:请求头,第二行到第 ...
- Spring源码知识概览
目录 Spring知识总览 1.1 IOC 1.2 Spring中重要接口概览 Spring知识总览 1.1 IOC IOC是控制反转,是一种思想 DI是依赖注入,是控制翻转的一种实现 Spring的 ...
- NB-IoT成为3GPP后会有哪些优势
NB-IoT无线接入的设计使用了很多LTE设计大的原则,并且得到了传统蜂窝网络和芯片组供应商的支持,使MBB取得了成功.NB-IoT采用与LTE(E-UTRA)相同的设计原则,尽管它使用单独的新载波, ...
- bat批处理常用脚本
windows下有很多场景需要编写批处理来解决问题,跟定时任务相结合使用更佳. 1.创建文件,md,mkdir都可以进行文件创建 set AwrPath=D:\OracleTabChk if not ...
- Java内存区域(运行时数据区域)详解、JDK1.8与JDK1.7的区别
2.1 概述 对Java程序员来说,在虚拟机自动内存管理机制的帮助下,不再需要为每个对象的new操作去写配对的delete/free 代码,不容易出现内存泄露和内存溢出的问题.不过,仍然需要Java虚 ...
- From delete library to run の 初见Django篇
一.虚拟环境简介 1.什么是虚拟环境? 虚拟环境是用于依赖项管理和项目隔离的python工具,允许python的第三方库安装在本地特定项目的隔离目录中,而不是全局安装. 2.虚拟环境的组成 ① 安装了 ...
- python实现常见的设计模式
Pyhton实现常用的23种设计模式[详解] 关注公众号[轻松学编程],回复[设计模式],获取本文源代码. 在文章末尾可以扫码关注公众号. 一.概念 软件工程中,设计模式是指软件设计问题的推荐方案. ...
- 微信小程序授权页面
这里也是比较简单的 直接复制粘贴就可以用,可能图片位置不对.. <template> <view id="imporwer"> <image src= ...