背景分析
当我们项目中的一些非核心业务运行时,影响到用户核心业务的响应时间,导致用户体验下降,我们该如何处理?
异步应用分析
当我们项目中的一些非核心业务运行时,因其耗时操作,影响到用户核心业务的响应时间,此时可以将这些非核心业务的耗时操作放到新的线程中异步执行。例如:
new Thread(new Runnable() {
@Override
public void run() {
//耗时操作
}
}).start();
对于如上形式的异步实现方式,在并发比较小的时候可以,但是一旦并发量比较大时,反复创建线程和销毁线程会带来很大系统开销,进而影响整体性能。
SpringBoot工程中的异步
启动异步
SpringBoot工程中默认支持异步操作,但是我们需要首先在启动类的上面,添加启动异步操作的注解(@EnableAsync)描述,代码如下:
@EnableAsync
@SpringBootApplication
public class DbpmsApplication {
public static void main(String[] args) {
SpringApplication.run(DbpmsApplication.class, args);
}
}
更多注解可参考博客:https://blog.csdn.net/weixin_53601359/article/details/114378460
定义切入点方法
假如此时某个业务方法需要执行异步操作,可以使用@Async注解对方法进行描述,例如写日志的业务,关键代码如下:
@Asyncpublic
void saveLog(SysLog entity){
//Log切面中调用的方法
sysLogDao.insertLog(entity)
}
其中,@Async注解描述的方法,在spring中会认为这是一个异步切入点方法,在这个切入点方法执行时,底层会通过通知方法获取线程池中的线程,通过池中的线程调用切入点方法(底层默认池类型为ThreadPoolExecutor类型)
自定义线程池的配置
当springboot中默认的线程池配置,不满足我们实际项目需求时,我们可以对线程池进行自定义的配置,关键配置如下:
spring.task.execution.pool.core-size=8
spring.task.execution.pool.max-size=256
spring.task.execution.pool.keep-alive=60000
spring.task.execution.pool.queue-capacity=512
spring.task.execution.thread-name-prefix=async-service-task-
其中:
- core-size :核心线程数,当池中线程数没达到core-size的值时,每接收一个新的任务都会创建一个新线程,然后存储到池。假如池中线程数已经达到core-size设置的值,再接收新的任务时,要检测是否有空闲的核心线程,假如有,则使用空闲的核心线程执行新的任务。
- queue-capacity:队列容量,假如核心线程数已达到core-size设置的值,并且所有的核心线程都在忙,再来新的任务,会将任务存储到任务队列。
- max-size: 最大线程数,当任务队列已满,核心线程也都在忙,再来新的任务则会创建新的线程,但所有线程数不能超过max-size设置的值,否则可能会出现异常(拒绝执行)
- keep-alive:线程空闲时间,假如池中的线程数多余core-size设置的值,此时又没有新的任务,则一旦空闲线程空闲时间超过keep-alive设置的时间值,则会被释放。
- thread-name-prefix:线程名的前缀,项目中设置线程名的目的主要是为了对线程进行识别,一旦出现线程问题,可以更好的定位问题。
更多常用配置可参考博客:https://blog.csdn.net/weixin_53601359/article/details/114416191