Java 多个 @Scheduled定时器不执行

最近项目中经常有用到@Scheduled注解,在内测时由于数据量小(没有进行压力测)所以每个线程执行都很快,但线上后发现部分功能无法使用,最后定位是部分的定时器没有执行,后查阅资料和Springboot源码后

Java 多个 @Scheduled定时器不执行_第1张图片

Java 多个 @Scheduled定时器不执行_第2张图片

ScheduledTaskRegistrar在启动时,如果没有指定线程池的大小,默认会创建核心线程数为1的默认线程池,故而当项目中出现多个@Scheduled线程时,只能一个个的执行,从而导致个别线程执行时间过长(或长期执行)时,其他定时器不能按照指定的规则进行执行。

解决方法

1.在项目初始化时指定其执行线程池的大小

import org.springframework.boot.autoconfigure.batch.BatchProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 程序名 : ScheduledTaskConfiguration
 * 建立日期: 2021-02-23 9:33
 * 模块 : Scheduled任务线程池设置
 * 描述 : 读取项目中使用了@Scheduled注解的方法,默认所有方法在项目创建时都需要按照设定的规则执行
 * 备注 : //TODO
 * 

* 修改历史 * 序号 日期 修改人 修改原因 */ @Configuration public class ScheduledTaskConfiguration implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { Method[] methods = BatchProperties.Job.class.getMethods(); final AtomicInteger corePoolSize = new AtomicInteger(); if (Objects.nonNull(methods) && methods.length > 0) { Arrays.stream(methods).forEach(method -> { final Scheduled annotation = method.getAnnotation(Scheduled.class); if (Objects.nonNull(annotation)) { corePoolSize.incrementAndGet(); } }); } ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(corePoolSize.get()); taskRegistrar.setScheduler(executor); } }

2.将定时器设置为异步线程

/**
异步线程
定时器延迟1秒启动,每距上一次执行完成后间隔3秒执行一次
*/
@Async("taskExecutor")
@Scheduled(initialDelay = 1000L, fixedDelay = 3000L)
public void test(){
   System.out.println("---"+System.currentTimeMillis());
 //业务内容
}

 

你可能感兴趣的:(Spring,Cloud,Spring,spring,boot,定时器)