关于springboot定时任务配置线程池之后任务重复执行问题,踩坑

关于springboot定时任务配置线程池之后任务重复执行问题,踩坑

最近遇到一个问题。项目中有一个job 的定时任务mytask。里面有七个定时任务。有3秒执行一次的,有五秒的,有十秒的,有两三分钟的,也有个把小时的。但是因为任务比较多,而springboot的定时任务Scheduled默认是单线程处理定时任务的。所以导致有任务会被阻塞,无法按时执行。就创建一个线程池,开启异步定时任务来解决。期间遇到了一个大坑。整了一天多的时间。才算解决。

先说一下我原来创建定时任务线程池的思路

定时任务的配置在这里就略过了,只说我再配置多线程异步任务的时候踩的坑

先创建一个类,配置异步线程池.

@Configuration
@EnableAsync
public class ScheduleConfig implements SchedulingConfigurer {

	@Override
	public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
		//设定一个长度15的定时任务线程池
        taskRegistrar.setScheduler(Executors.newScheduledThreadPool(15));
		
	}
	
	/**
     * 异步线程池设置
     * 如果所有的任务都使用异步,线程池执行的话,可以不配置同步任务线程池。
     * 但是使用异步需要注意的是异步线程池的大小配置。异步的线程池默认是无上限的开启线程数的。
     * @return
     */
    @Bean
    SimpleAsyncTaskExecutor simpleAsyncTaskExecutor(){
        SimpleAsyncTaskExecutor simpleAsyncTaskExecutor = new SimpleAsyncTaskExecutor();
        simpleAsyncTaskExecutor.setConcurrencyLimit(7);		//设置最大并行数
        simpleAsyncTaskExecutor.setDaemon(true); 	//设置为守护线程
        return  simpleAsyncTaskExecutor;
    }

}

然后在定时任务中添加@Async注解开启异步调用

关于springboot定时任务配置线程池之后任务重复执行问题,踩坑_第1张图片

当时也没有发现有什么异常,部署到服务器上一段时间之后,发现数据库中入库的数据有重复。查看日志发现了一个很大的问题。一个任务会重复执行多次,导致数据库中入库的数据重复。
关于springboot定时任务配置线程池之后任务重复执行问题,踩坑_第2张图片

在网上找相关问题(有需要的可以去链接里面试试看能不能解决):
有说是因为Tomcat配置问题的,导致项目被初始化两次导致的
有说是因为DispatcherServlet 相关配置问题的
也有说是因为quartz重复调度导致任务重复执行的
总之网上的说法不一,有很多解决办法,我也都一一的试过了,都不管用。

就只能自己慢慢尝试着修改来找问题出在哪儿了!

后来就想到是不是因为项目启动在扫描的时候。启用可两个线程池,导致的两个线程池同时对一个任务生效。(/狗头保命,只是这样想的啊~ 我也不知道对不对。毕竟我也是第一次配置这个异步定时任务,连最初的配置都是网上借鉴的。有说的不对的,或者犯低级错误的,大家轻点儿喷

继续说怎么解决的:
想到可能是因为有两个线程池同时被扫描创建导致的任务重复执行。我就把最开始创建的那个线程池得类给合并到启动类中了。
就这个亚子关于springboot定时任务配置线程池之后任务重复执行问题,踩坑_第3张图片
然后我再启动项目,就…发现神奇的好了。反正就很神奇。

肯定会有人说,你解决的这是个屁啊,都不管用什么的。网上有那么多解决办法。这个不行麻烦你就出门右转,谢谢。最后附上两张解决前后的日志截图。
同一个定时任务的定时日志截图。
关于springboot定时任务配置线程池之后任务重复执行问题,踩坑_第4张图片
关于springboot定时任务配置线程池之后任务重复执行问题,踩坑_第5张图片

******************************** 更新一下上面的那个错误解决的具体情况 *********************************

具体出错的原因找到了。今天在对比看git提交记录的时候发现的。在从网上参考定时任务线程池的时候再启动类中多继承了一次 SpringBootServletInitializer 直接上图。
关于springboot定时任务配置线程池之后任务重复执行问题,踩坑_第6张图片
因为项目中已经有了一个单独的类继承 SpringBootServletInitializer了,然后又在启动类中又继承了一遍。导致的job定时在运行的时候所有的任务都执行两次。(大意了,确实是很小的问题,找了好久没找到。今天在对比提交的历史代码的时候才发现的。)

关于springboot定时任务配置线程池之后任务重复执行问题,踩坑_第7张图片

你可能感兴趣的:(框架-springboot,踩坑,java)