如何在Spring中使用EnableScheduling注释在运行时重新启动计划任务? [英] How to restart scheduled task on runtime with EnableScheduling annotation in spring?

查看:2162
本文介绍了如何在Spring中使用EnableScheduling注释在运行时重新启动计划任务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在研究如何使用Java 8和spring在运行时更改作业的频率。 此问题非常有用,但它并没有完全解决我的问题。

I have been investigating how to change the frequency of a job on runtime with Java 8 and spring. This question was very useful but it did not totally solve my issue.

我现在可以配置下次执行作业的日期。但是如果将延迟设置为1年,那么我需要在考虑新配置之前等待1年。

I can now configure the date when to job should be executed next. But If set the delay to 1 year, then I need to wait 1 year before the new configuration in taken into account.

我的想法是停止计划任务配置值已更改(因此从另一个类)。然后在下次执行任务时重新计算。也许还有一种更简单的方法。

My idea would be to stop the scheduled task if the configuration value is changed (so from another class). Then recalculate the next time the task should be executed. Perhaps there is an easier way of doing this.

这是我到目前为止的代码。

Here is the code I have so far.

@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";
    }

}


推荐答案


  1. 创建一个获取注入的单例bean TaskScheduler 。这将作为状态变量保存所有 ScheduledFuture s ,如私有ScheduledFuture job1;

  2. 部署时,从中加载数据库所有计划数据并启动作业,填写所有状态变量,如 job1

  3. 关于更改计划数据,取消相应的 Future (例如 job1 ),然后使用新的计划数据再次启动它。

  1. Create a singleton bean that gets an injected TaskScheduler. This will hold as state variables all ScheduledFutures, like private ScheduledFuture job1;
  2. On deployment, load from databases all schedule data and start the jobs, filling in all state variables like job1.
  3. On change of scheduling data, cancel the corresponding Future (e.g job1) and then start it again with the new scheduling data.

这里的关键思想是在创建时控制 Future ,以便将它们保存在某些状态变量,以便当调度数据中的某些内容发生变化时,您可以取消它们。

The key idea here is to get control on the Futures as they are created, so to save them in some state variables, so that when something in scheduling data changes, you can cancel them.

这是工作代码:

applicationContext.xml

applicationContext.xml

<task:annotation-driven />
<task:scheduler id="infScheduler" pool-size="10"/>

单例bean,包含 Future s

The singleton bean, that holds the Futures

@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);
                }
        }
}

这篇关于如何在Spring中使用EnableScheduling注释在运行时重新启动计划任务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆