Python 官方文档:入门教程 => 点击学习
目录前言 使用步骤 配置线程池类参数配置 自定义线程任务 总结 原理刨析 文章参考 前言 在实际项目开发中很多业务场景需要使用异步去完成,比如消息通知,日志记录,等非常常用的都可以
在实际项目开发中很多业务场景需要使用异步去完成,比如消息通知,日志记录,等非常常用的都可以通过异步去执行,提高效率,那么在spring框架中应该如何去使用异步呢
完成异步操作一般有两种,消息队列MQ,和线程池处理ThreadPoolExecutor
而在Spring4中提供的对ThreadPoolExecutor封装的线程池ThreadPoolTaskExecutor,直接使用注解启用@Async,这个注解让我们在使用Spring完成异步操作变得非常方便
自定义常量类
public class ConstantFiledUtil {
public static final String AUTHORIZATioN_TOKEN = "authorizationToken";
public static final String KMALL_THREAD_POOL = "KmallThreadPool";
public static final String KMALL_THREAD_NAME_PREFIX = "kmall-thread-";
}
配置线程池
@Configuration(proxyBeanMethods = false)
@EnableAsync //开启注解
public class KmallConfig {
@Bean(ConstantFiledUtil.KMALL_THREAD_POOL)
public ThreadPoolTaskExecutor FebsshiroThreadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//配置核心线程数
executor.setCorePoolSize(5);
//配置最大线程数
executor.setMaxPoolSize(20);
//配置队列大小
executor.setQueueCapacity(200);
//线程池维护线程所允许的空闲时间
executor.seTKEepAliveSeconds(30);
//配置线程池中的线程的名称前缀
executor.setThreadNamePrefix(ConstantFiledUtil.KMALL_THREAD_NAME_PREFIX);
//设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean
executor.setWaitForTasksToCompleteOnShutdown(true);
//设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住
executor.setAwaitTerminationSeconds(60);
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//执行初始化
executor.initialize();
return executor;
}
}
注意这里需要通过@EnableAsync开启异步否则无效
public interface ILogService extends IService<Log> {
IPage getSearchLogByPage(SearchLogParams logParams);
@Async
void saveLog(LogSubject logSubject);
}
在需要异步执行的接口,或者方法上加上@Async注解此方法就是异步方法,在主程序中调用的化,就是异步方式单独线程执行
此注解表明saveLog方法进入的线程池是KmallThreadPool方法创建的。
我们也可以单独指定方法名称@Async("saveLogs")
这样在进行日记记录的时候就是单独线程执行每次请求都快速响应了,而耗时的操作都留给线程池中的线程去异步执行
Spring中用@Async注解标记的方法,称为异步方法。在Spring Boot应用中使用@Async很简单:
注意同一个类里面调用异步方法不生效:原因默认类内的方法调用不会被aop拦截,即调用方和被调用方是在同一个类中,是无法产生切面的,该对象没有被Spring容器管理。即@Async方法不生效
解决办法:
如果要使同一个类中的方法之间调用也被拦截,需要使用spring容器中的实例对象,而不是使用默认的this,因为通过bean实例的调用才会被spring的aop拦截
本例使用方法:AsyncService asyncService = context.getBean(AsyncService.class); 然后使用这个引用调用本地的方法即可达到被拦截的目的
备注:这种方法只能拦截protected,default,public方法,private方法无法拦截。这个是spring aop的一个机制。
异步方法返回类型只能有两种:
注意如果不自定义异步方法的线程池默认使用SimpleAsyncTaskExecutor。SimpleAsyncTaskExecutor:不是真的线程池,这个类不重用线程,每次调用都会创建一个新的线程。并发大的时候会产生严重的性能问题。
Spring异步线程池接口 TaskExecutor
看源码可知
@FunctionalInterface
public interface TaskExecutor extends Executor {
void execute(Runnable var1);
}
它的实先类有很多如下:
--结束END--
本文标题: SpringBoot异步使用@Async的原理以及线程池配置详解
本文链接: https://www.lsjlt.com/news/135738.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0