我一直在研究如何使用 Java 8 和 spring 在运行时更改作业的频率。 This question非常有用,但并没有完全解决我的问题。
我现在可以配置下一次执行作业的日期。但是如果将延迟设置为 1 年,那么我需要等待 1 年才能考虑到新配置。
我的想法是如果配置值发生更改(因此来自另一个类),则停止计划任务。然后重新计算下一次应该执行的任务。也许有更简单的方法来做到这一点。
这是我目前的代码。
@Configuration
@EnableScheduling
public class RequestSchedulerConfig implements SchedulingConfigurer {
@Autowired
SchedulerConfigService schedulerConfigService;
@Bean
public RequestScheduler myBean() {
return new RequestScheduler();
}
@Bean(destroyMethod = "shutdown")
public Executor taskExecutor() {
return Executors.newScheduledThreadPool(100);
}
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
taskRegistrar.addTriggerTask(
new Runnable() {
@Override public void run() {
myBean().startReplenishmentComputation();
}
},
new Trigger() {
@Override public Date nextExecutionTime(TriggerContext triggerContext) {
Duration d = schedulerConfigService.getIntervalFromDB();
return DateTime.now().plus(d).toDate();
}
}
);
}
}
这就是我想做的。
@RestController
@RequestMapping("/api/config/scheduler")
public class RequestSchedulerController {
@Autowired
ApplicationConfigWrapper applicationConfigWrapper;
@RequestMapping("/set/")
@ResponseBody
public String setRequestSchedulerConfig(@RequestParam(value = "frequency", defaultValue = "") final String frequencyInSeconds){
changeValueInDb(frequencyInSeconds);
myJob.restart();
return "Yeah";
}
}
最佳答案
- 创建一个获得注入(inject)的单例 bean
TaskScheduler
.这将作为状态变量保存所有ScheduledFuture
s ,例如private ScheduledFuture job1;
- 在部署时,从数据库加载所有计划数据并启 Action 业,填写所有状态变量,如
job1
。 - 关于调度数据的变化,cancel对应的
Future
(例如job1
),然后用新的调度数据重新开始。
这里的关键思想是在创建 Future
时对其进行控制,以便将它们保存在一些状态变量中,这样当调度数据中的某些内容发生变化时,您可以取消它们。
这是工作代码:
applicationContext.xml
<task:annotation-driven />
<task:scheduler id="infScheduler" pool-size="10"/>
持有 Future
s
@Component
public class SchedulerServiceImpl implements SchedulerService {
private static final Logger logger = LoggerFactory.getLogger(SchedulerServiceImpl.class);
@Autowired
@Qualifier(value="infScheduler")
private TaskScheduler taskScheduler;
@Autowired
private MyService myService;
private ScheduledFuture job1;//for other jobs you can add new private state variables
//Call this on deployment from the ScheduleDataRepository and everytime when schedule data changes.
@Override
public synchronized void scheduleJob(int jobNr, long newRate) {//you are free to change/add new scheduling data, but suppose for now you only want to change the rate
if (jobNr == 1) {//instead of if/else you could use a map with all job data
if (job1 != null) {//job was already scheduled, we have to cancel it
job1.cancel(true);
}
//reschedule the same method with a new rate
job1 = taskScheduler.scheduleAtFixedRate(new ScheduledMethodRunnable(myService, "methodInMyServiceToReschedule"), newRate);
}
}
}
关于java - 如何在 Spring 使用 EnableScheduling 注释在运行时重新启动计划任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31969251/