视频软件App开发引领数字内容创作与分享的新时代
529
2022-11-11
springboot使用定时器@Scheduled不管用的解决
目录使用定时器@Scheduled不管用多个@Scheduled定时器不执行解决方法
使用定时器@Scheduled不管用
如果是一开始就不能用就是没写@EnableScheduling注解,如果是用着用着不管用了 是因为@Scheduled是单线程,有定时器在工作或者没有运行完毕,所以造成了线程堵塞所以导致下一个定时器不能运行增加一个方法类
package com.llt;
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.concurrent.Executors;wberBX
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
Method[] methods = BatchProperties.Job.class.getMethods();
int defaultPoolSize = 3;
int corePoolSize = 0;
if (methods != null && methods.length > 0) {
for (Method method : methods) {
Scheduled annotation = method.getAnnotation(Scheduled.class);
if (annotation != null) {
corePoolSize++;
}
}
if (defaultPoolSize > corePoolSize)
corePoolSize = defaultPoolSize;
}
taskRegistrar.setScheduler(Executors.newScheduledThreadPool(corePoolSize));
}
}
就好了!
多个@Scheduled定时器不执行
最近项目中经常有用到@Scheduled注解,在内测时由于数据量小(没有进行压力测)所以每个线程执行都很快,但线上后发现部分功能无法使用,最后定位是部分的定时器没有执行,后查阅资料和Springboot源码后
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;
/**
* 程序名 : SwberBXcheduledTaskConfiguration
* 建立日期: 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());
//业务内容
}
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~