目录
1.SpringBoot整合ThreadPoolTaskExecutor线程池
1.1.2注入Executor或者ThreadPoolTaskExecutor创建线程
3.2通过Executor或者ThradPoolTaskExecutor注解启动多线程
3.3@Async和@Transactional注解一起使用生效
1.SpringBoot整合ThreadPoolTaskExecutor线程池
1.1使用springboot默认配置
默认配置可以在配置文件里面修改
1.1.1@Async开启线程
在启动类上面开启异步,使用注解@EnableAsync,再使用@Async开启线程,使用SpringBoot内置的线程池
1.1.2注入Executor或者ThreadPoolTaskExecutor创建线程
ThreadPoolExecutor:我们经常用这个线程池创建线程,这个大家一定不陌生,JDK自带线程池
ThradPoolTaskExecutor:这个是SpringBoot基于ThreadPoolExecutor实现的线程池类,可以进去ThradPoolTaskExecutor类可以看下
springboot会自动配置一个ThreadPoolTaskExecutor线程池到bean当中,我们在使用默认配置可以直接注入ThradPoolExecutor
1.2自定义线程池配置
自定义配置线程池后用法和上面几乎一样,就是需要注意自己的创建bean id,在创建线程的时候需要使用自己命名的线程池名字即截图中taskExecutor作为线程池
2.线程失效问题分析
2.1@EnableAsync没有开启
没有开启异步是不会生效的,即虽然使用了@Async注解还是同步,不会有两个线程。需要在启动类或者配置类上开启异步。
2.2异步方法不是public和protected
通过注解开启新线程,异步方法使用private修改无法启动一个异步线程,修饰符需要是public,因为代理需要public才可以创建动态代理
controller
BenjaminService
BenjaminServiceImpl
AsyncService
2.3同类异步方法调用
同类方法内调用不生效,调用方和被调用方在一个类中不生效
1.拆分服务,将异步方法移动到另一个spring管理的bean中
2.自我注入,spring允许将当前类注入到自己实例中,这样就可以通过代理调用异步方法
controller
BenjaminService
BenjaminServiceImpl
方法1:拆分服务到其他类,这个类交给spring容器管理,通过注入异步类调用开启多线程
AsyncService
方法2:注入自身,通过自身调用多线程方法
2.4new对象调用
通过new出来的对象没有交给spring容器管理,不能创建动态代理,使用@Async注解不生效
controller
BenjaminService
BenjaminServiceImpl
AsyncService
3.正确使用开启新线程
3.1通过@Async注解启动多线程
不再同一个类中调用、修饰符public是可以创建多线程的
controller
BenjaminService
BenjaminServiceImpl
AsyncService
3.2通过Executor或者ThradPoolTaskExecutor注解启动多线程
通过Executor或者ThradPoolTaskExecutor注解启动多线程 在同一个类也是可以的,就是手动创建多线程
controller
BenjaminService
BenjaminServiceImpl
3.3@Async和@Transactional注解一起使用生效
@Async和@Transactional注解一起使用生效的,有些blog说不生效,我暂时没有找到问题,在表中模拟异常事务回滚生效,开启多线程在在没有同步工具阻塞主线程的前提下,多线程也是异步的,因此@Async和@Transactional是可以同时使用的。
controller
BenjaminService
BenjaminServiceImpl
AsyncService
4源码
源码下载地址
https://download.youkuaiyun.com/download/m0_48983233/90210759http://xn--ghqu6tnb340mkpkxk8a亲测:
拒绝白嫖,转载请说明原blog地址