java根据springboot@Scheduled注释使用的条件动态修改调度程序计时
我有一个调度程序,它以5秒的固定延迟触发
我计划有多个调度器,但现在,让我们只使用一个调度器
要求:应根据业务情况更改计划程序的固定延迟
**例如,**默认固定延迟为5秒,但根据条件,它可以是6、8、10秒。
因此,为了实现这一点,我试图修改fixedDelay。
但这对我不起作用
代码:
接口,使用延迟方法
public abstract class DynamicSchedule{
/**
* Delays scheduler
* @param milliseconds - the time to delay scheduler.
*/
abstract void delay(Long milliseconds);
/**
* Decreases delay period
* @param milliseconds - the time to decrease delay period.
*/
abstract void decreaseDelayInterval(Long milliseconds);
/**
* Increases delay period
* @param milliseconds - the time to increase dela period
*/
abstract void increaseDelayInterval(Long milliseconds);
}
实现位于组织的触发器接口。springframework。spring上下文项目中的调度。
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import java.util.Date;
import java.util.concurrent.ScheduledFuture;
public class CustomDynamicSchedule extends DynamicSchedule implements Trigger {
private TaskScheduler taskScheduler;
private ScheduledFuture<?> schedulerFuture;
/**
* milliseconds
*/
private long delayInterval;
public CustomDynamicSchedule(TaskScheduler taskScheduler) {
this.taskScheduler = taskScheduler;
}
@Override
public void increaseDelayInterval(Long delay) {
if (schedulerFuture != null) {
schedulerFuture.cancel(true);
}
this.delayInterval += delay;
schedulerFuture = taskScheduler.schedule(() -> { }, this);
}
@Override
public void decreaseDelayInterval(Long delay) {
if (schedulerFuture != null) {
schedulerFuture.cancel(true);
}
this.delayInterval += delay;
schedulerFuture = taskScheduler.schedule(() -> { }, this);
}
@Override
public void delay(Long delay) {
if (schedulerFuture != null) {
schedulerFuture.cancel(true);
}
this.delayInterval = delay;
schedulerFuture = taskScheduler.schedule(() -> { }, this);
}
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
Date lastTime = triggerContext.lastActualExecutionTime();
return (lastTime == null) ? new Date() : new Date(lastTime.getTime() + delayInterval);
}
}
配置:
@Configuration
public class DynamicSchedulerConfig {
@Bean
public CustomDynamicSchedule getDinamicScheduler() {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.initialize();
return new CustomDynamicSchedule(threadPoolTaskScheduler);
}
}
测试类,以测试使用情况
@EnableScheduling
@Component
public class TestSchedulerComponent {
@Autowired
private CustomDynamicSchedule dynamicSchedule;
@Scheduled(fixedDelay = 5000)
public void testMethod() {
dynamicSchedule.delay(1000l);
dynamicSchedule.increaseDelayInterval(9000l);
dynamicSchedule.decreaseDelayInterval(5000l);
}
}
我得到了https://stackoverflow.com/a/51333059/4770397的帮助,
但不幸的是,这个代码对我不起作用
调度程序正在fixedDelay上运行,这方面没有变化
请帮忙
# 1 楼答案
有了注释,你只能通过找到一个公分母并进行投票来进行近似运算。我一会儿给你看。如果您想要一个真正的动态解决方案,您不能使用注释,但可以使用编程配置此解决方案的优点是,您甚至可以在运行时更改执行周期下面是一个如何做到这一点的示例:
有一种方法可以欺骗并实际使用注释。但只有在精度不重要的情况下,你才能做到这一点。精确是什么意思。如果你知道你想每5秒启动一次,但100毫秒左右并不重要。如果您知道需要每5-6-8或10秒启动一次,那么可以配置每秒执行一次的作业,并在一条If语句中检查自上次执行以来已过了多长时间。这是非常蹩脚的,但它可以工作:)只要你不需要高达毫秒的精度。下面是一个例子:
我有点跛脚,但我会为简单的案件做这项工作
# 2 楼答案
Spring的
@Scheduled
注释不提供这种支持。这是我首选的使用基于队列的解决方案实现类似功能的方法,该解决方案允许灵活的计时和非常健壮的调度器功能实现。
这是管道-
cron
和一个单线程执行器服务,负责根据Cron将消息发布到队列。task-cron
映射被持久化在database
中,并在启动期间初始化。此外,我们还公开了一个API
,用于在运行时更新任务的cron。我们只需关闭旧的scheduled executor服务,并在通过API触发cron更改时创建一个服务。此外,我们还更新了数据库中的数据
这种方法有很多优点。这将使调度器与计划管理任务分离。现在,调度器可以只关注业务逻辑。此外,我们可以编写任意多个调度器,所有调度器都监听同一个队列,并相应地执行操作
# 3 楼答案
使用
@Scheduled
只允许使用静态计划。您可以使用属性使计划可以这样配置但是,一旦spring上下文初始化(应用程序启动),生成的时间表将被修复
要获得对计划执行的细粒度控制,您需要实现一个定制的^{} ——类似于您已经做过的。与待执行任务一起,可以通过使用^{} 在} 来注册此触发器:
@Configuration
类中实现^{但是不要在
CustomDynamicSchedule
中注册任务,只需使用它来计算下一次执行时间:但请记住要使
CustomDynamicSchedule
线程安全,因为它将在spring中创建为单线程,并且可能被多个线程并行访问