关注微信公众号:CodingTechWork,一起学习进步。
问题
在使用Spring
中的@Scheduled
注解设置定时任务时,遇到这样2个问题:
- 定时任务未按时执行,现象是延后了一段时间才执行定时任务。
- 多个定时任务有时间重叠时,无法并发调度执行。
分析
出现上面问题现象的根因是Spring的定时任务默认是单线程执行,所以会在某些场景下造成阻塞。当然我们可以通过@Async
注解来异步执行这些并发的@Scheduled
注解的定时任务,而@Async
线程池容量是100,当超过100个线程并发执行时,则剩下的定时任务会等待之前的线程释放,不会自行扩容。
既然@Async是个定值大小的线程池,还是有出现定时任务延时执行的问题,所以下面我们可以通过其他方式来自定义线程池大小。
解决方式
通过自定义配置线程池来解决问题。
package com.andya.selfcode.conf;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.util.concurrent.*;
/**
* @author Andya
* @create 2021-03-31
*/
@Slf4j
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
//自定义线程池大小,可配置。代码中默认10个
@Value("${threadPool.schedule.coreSize: 10}")
public int SCHEDULE_CORE_SIZE;
//自定义线程池名称
public static final String THREAD_NAME_WITH_SCHEDULE = "schedule-thread-%d";
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
// scheduledTaskRegistrar.setScheduler(Executors.newScheduledThreadPool(SCHEDULE_CORE_SIZE));
scheduledTaskRegistrar.setScheduler(this.buildSchedulerThreadPool());
System.out.println("Scheduler threadpool core_size: " + SCHEDULE_CORE_SIZE);
}
/**
* Spring的@Scheduled的自定义周期性线程池
* @return
*/
@Bean(value = "scheduleThreadPool")
public ExecutorService buildSchedulerThreadPool() {
ThreadFactory threadFactory = new ThreadFactoryBuilder()
.setNameFormat(THREAD_NAME_WITH_SCHEDULE).build();
/**
* 1. CallerRunsPolicy : 这个策略重试添加当前的任务,他会自动重复调用 execute() 方法,直到成功。
2. AbortPolicy : 对拒绝任务抛弃处理,并且抛出异常。
3. DiscardPolicy : 对拒绝任务直接无声抛弃,没有异常信息。
4. DiscardOldestPolicy : 对拒绝任务不抛弃,而是抛弃队列里面等待最久的一个线程,然后把拒绝任务加到队列。
不写则为默认的AbortPolicy策略。
*/
ScheduledExecutorService threadPool = new ScheduledThreadPoolExecutor(
SCHEDULE_CORE_SIZE,
threadFactory);
return threadPool;
}
}
网友评论