springboot异步线程(二)
前言
上一篇中讲了关于TaskExecutor
的一些相关知识,本篇就是实战篇,看看异步线程使如何使用的
正文
本篇文章使用springboot 2.2.1.RELEASE
一.前奏,直接使用,无任何配置
- 启动异步注解
在springboot启动类上添加注解@EnableAsync
@SpringBootApplication
@EnableAsync
public class AsyncApplication {
public static void main(String[] args) {
SpringApplication.run(AsyncApplication.class, args);
}
}
- 使用@Async注解
在需要的方法上使用@Async注解:
public interface AsyncService {
@Async
void testAsync();
@Async
void testOne();
}
@Service
public class AsyncServiceImpl implements AsyncService {
private static final Logger log= LoggerFactory.getLogger(AsyncServiceImpl.class);
@Override
public void testAsync(){
log.info("========testAsync运行=========="+Thread.currentThread().getName());
}
@Override
public void testOne(){
log.info("ThreadName:===one===="+Thread.currentThread().getName());
}
}
- controller 调用
在controller层调用异步方法,注意,异步方法最好通过注入的方式调用,如果是同类方法或工具类方法,@Async可能不会取作用。
@RestController
@RequestMapping("/test")
public class TestController {
private final AsyncService asyncService;
@Autowired
public TestController(AsyncService asyncService) {
this.asyncService = asyncService;
}
@GetMapping
public String test(){
asyncService.testAsync();
asyncService.testOne();
return "SUCCESS";
}
}
- 结果
2019-12-27 15:06:30.159 INFO 14756 --- [ task-1] c.e.async.service.impl.AsyncServiceImpl : ========testAsync运行==========task-1
2019-12-27 15:06:30.160 INFO 14756 --- [ task-2] c.e.async.service.impl.AsyncServiceImpl : ThreadName:===one====task-2
- 问题
很多人到这里就差不多完事了,我第一次用springboot
的异步也是这样。其实这里还有问题:
- 为什么线程名字是
task-
,而不是很多博客所说的SimpleAsyncTaskExecutor-
- 为什么应用在启动时创建了一个名为:
applicationTaskExecutor
的Executor Service
- 原因
这是因为springboot版本的原因:
springboot2.1
版本新加入了明为TaskExecutionAutoConfiguration
的一个配置类,在没有实现Executor
的情况是会自动注入一个name
为applicationTaskExecutor
的ThreadPoolTaskExecutor
,具体属性可以点进去看一看,这里就不细说了,关键源码如下:
@Lazy
@Bean(name = { APPLICATION_TASK_EXECUTOR_BEAN_NAME,
AsyncAnnotationBeanPostProcessor.DEFAULT_TASK_EXECUTOR_BEAN_NAME })
@ConditionalOnMissingBean(Executor.class)
public ThreadPoolTaskExecutor applicationTaskExecutor(TaskExecutorBuilder builder) {
return builder.build();
}
- 在
springboot2.1
版本之前,没有这个TaskExecutionAutoConfiguration
类,所以才会是网上很多博客所说的SimpleAsyncTaskExecutor
,具体的源码在下一篇文章中讲
二. ThreadPoolTaskExecutor
如何使用ThreadPoolTaskExecutor。
@Configuration
public class AsyncConfig {
@Bean(name = "threadPoolTaskExecutor")
public ThreadPoolTaskExecutor testTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
executor.setThreadNamePrefix("courses-schedule-");
//最大线程数10:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
executor.setMaxPoolSize(10);
//核心线程数3:线程池创建时候初始化的线程数
executor.setCorePoolSize(3);
//缓冲队列0:用来缓冲执行任务的队列
executor.setQueueCapacity(5);
//允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
executor.setKeepAliveSeconds(60);
// 当线程池已满,且等待队列也满了的时候,直接抛弃当前线程(不会抛出异常)
// executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
// executor.initialize();
return executor;
}
}
注意在使用@Async
注解时在注解里面带上参数:@Async("threadPoolTaskExecutor")
三. ConcurrentTaskExecutor
如何使用ConcurrentTaskExecutor。
@Bean(name = "concurrentTaskExecutor")
public TaskExecutor concurrentTaskExecutor () {
return new ConcurrentTaskExecutor(
Executors.newFixedThreadPool(3));
}
注意在使用@Async
注解时在注解里面带上参数:@Async("concurrentTaskExecutor")
四 接口实现
AsyncConfig:这里需要实现AsyncConfigurer
接口并重写里面得接口
@Configuration
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
executor.setThreadNamePrefix("courses-schedule-");
//最大线程数10:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
executor.setMaxPoolSize(10);
//核心线程数3:线程池创建时候初始化的线程数
executor.setCorePoolSize(3);
//缓冲队列0:用来缓冲执行任务的队列
executor.setQueueCapacity(5);
//允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
executor.setKeepAliveSeconds(60);
// 当线程池已满,且等待队列也满了的时候,直接抛弃当前线程(不会抛出异常)
// executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
// executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
}
AsyncExceptionHandler:
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
System.out.println("Exception Cause - " + throwable.getMessage());
System.out.println("Method name - " + method.getName());
for (Object param : obj) {
System.out.println("Parameter value - " + param);
}
}
}
这个直接使用,不用做其他操作
五 说明
- 上面列出的方式,可以根据自己的需求做出选择,最好选择一种
- 如果存在两种及以上,请在使用
@Async
时加上需要使用哪一个处理,如果没有指明使用哪一种处理,最后会默认使用SimpleAsyncTaskExecutor
来处理异步任务。
最后
本篇文章主要是使用方法,如何去使用springboot的异步线程。
参考:
- Spring Boot Async Task Executor
- Spring 官方文档
- 新手也能看懂的 SpringBoot 异步编程指南
- TaskExecutionAutoConfiguration
springboot异步线程(二)的更多相关文章
- SpringBoot 异步线程简单三种样式
引用:在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在Spring 3.x ...
- springboot异步线程
前言 最近项目中出现了一个问题,发现自己的定时器任务在线上没有执行,但是在线下测试时却能执行,最后谷歌到了这篇文章SpringBoot踩坑日记-定时任务不定时了?; 本篇文章主要以自己在项目中遇到的问 ...
- SpringBoot第十二集:度量指标监控与异步调用(2020最新最易懂)
SpringBoot第十二集:度量指标监控与异步调用(2020最新最易懂) Spring Boot Actuator是spring boot项目一个监控模块,提供了很多原生的端点,包含了对应用系统的自 ...
- SpringBoot使用异步线程池实现生产环境批量数据推送
前言 SpringBoot使用异步线程池: 1.编写线程池配置类,自定义一个线程池: 2.定义一个异步服务: 3.使用@Async注解指向定义的线程池: 这里以我工作中使用过的一个案例来做描述,我所在 ...
- springboot 中如何正确在异步线程中使用request
起因: 有后端同事反馈在异步线程中获取了request中的参数,然后下一个请求是get请求的话,发现会偶尔出现参数丢失的问题. 示例代码: @GetMapping("/getParams&q ...
- Spring Boot系列二 Spring @Async异步线程池用法总结
1. TaskExecutor Spring异步线程池的接口类,其实质是java.util.concurrent.Executor Spring 已经实现的异常线程池: 1. SimpleAsyncT ...
- SpringBoot异步使用@Async原理及线程池配置
前言 在实际项目开发中很多业务场景需要使用异步去完成,比如消息通知,日志记录,等非常常用的都可以通过异步去执行,提高效率,那么在Spring框架中应该如何去使用异步呢 使用步骤 完成异步操作一般有两种 ...
- C#中的线程二(Cotrol.BeginInvoke和Control.Invoke)
C#中的线程二(Cotrol.BeginInvoke和Control.Invoke) 原文地址:http://www.cnblogs.com/whssunboy/archive/2007/06/07/ ...
- net异步线程获取返回值的三种方式
方式一:endInvoke using System; using System.Collections.Generic; using System.Text; using System.Thread ...
随机推荐
- Numpy | 14 字符串函数
本章函数用于对 dtype 为 numpy.string_ 或 numpy.unicode_ 的数组执行向量化字符串操作. 它们基于 Python 内置库中的标准字符串函数. 这些函数在字符数组类(n ...
- 关于System.TypeInitializationException异常
什么是System.TypeInitializationException 作为类初始值设定项引发的异常的包装器而引发的异常. 继承 Object Exception SystemException ...
- pycharm进行个性化设置
1. 设置主题:Monokai Ctrl+Alt+S: Editor->Color&Fonts->Python 2. 修改[选中内容]颜色 因为用了Monokai主题后,选中内容的 ...
- 字典树(Trie)学习笔记
目录 什么是字典树 如何存储字典树 如何查找字符串有没有出现 第一个图的那种线段树 应用 例题 1.统计难题 2.P2580 于是他错误的点名开始了 什么是字典树 上图来自luogu题解 这是一种字典 ...
- 代码注入/文件包含 弹出Meterpreter
主要通过 msf 中 exploit 的 web_delivery 模块来实现此功能 0x01 前提背景 目标设备存在远程文件包含漏洞或者命令注入漏洞,想在目标设备上加载webshell,但不想在目标 ...
- WAMP配置允许外网访问、绑定域名
如果wamp默认端口已经被占用,需要修改,则打开apache目录下的,conf文件下的httpd.conf文件 如图,把框中的默认80端口修改为自己需要的端口,然后重启WAMP即可. 想要实现外网访问 ...
- js操作表格、table、
js添加一行.删除一行 let str="<tr>" +"<td>"+a[1]+"</td>" +&qu ...
- 深入分析Synchronized原理(阿里面试题)
还有一篇 讲解lock的实现原理,参考:解决多线程安全问题-无非两个方法synchronized和lock 具体原理以及如何 获取锁AQS算法 (百度-美团) 记得开始学习Java的时候,一遇到多线程 ...
- [Gamma]Scrum Meeting#1
github 本次会议项目由PM召开,时间为5月26日晚上10点30分 时长25分钟 任务表格 人员 昨日工作 下一步工作 木鬼 撰写博客,组织例会 swoip 前端显示屏幕,翻译坐标 bhlt 后端 ...
- postgresql cstore_fdw安装与性能测试
据介绍,cstore_fdw实现了 PostgreSQL 数据库的列式存储.列存储非常适合用于数据分析的场景,数据分析的场景下数据是批量加载的.这个扩展使用了Optimized Row Columna ...