java - 如何在 Spring 使用 EnableScheduling 注释在运行时重新启动计划任务?

标签 java spring java-8 scheduled-tasks jobs

我一直在研究如何使用 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";
    }

}

最佳答案

  1. 创建一个获得注入(inject)的单例 bean TaskScheduler .这将作为状态变量保存所有 ScheduledFutures ,例如 private ScheduledFuture job1;
  2. 在部署时,从数据库加载所有计划数据并启 Action 业,填写所有状态变量,如 job1
  3. 关于调度数据的变化,cancel对应的Future(例如job1),然后用新的调度数据重新开始。

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

这是工作代码:

applicationContext.xml

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

持有 Futures

的单例 bean
@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/

相关文章:

java - 从服务器下载图像位图在 Android 2.2 上返回 null

Java递归理解

java - 如果应用程序使用不同于 MySQL 的时区,则 Hibernate 保存/检索日期减去天数

java - Spring 验证 - 避免重复的约束消息

javascript - 前端应用程序中的 JWT 身份验证流程?

java - Lambda 重载方法

java - 在 Java 中生成 CPU 负载

java - Spring-boot 应用程序,H2 嵌入式数据库 - 但当应用程序关闭时表会消失

java - 如何在 anyMatch() java 8 流中应用复合 BiPredicate

带有 ForEach 迭代问题的 Java Stream