如何停止使用@Scheduled 注释启动的计划任务?

新手上路,请多包涵

我使用 Spring Framework 的 @Scheduled 注释创建了一个简单的计划任务。

  @Scheduled(fixedRate = 2000)
 public void doSomething() {}

现在我想在不再需要时停止这项任务。

我知道可能有一种替代方法可以在此方法开始时检查一个条件标志,但这不会停止执行此方法。

Spring 提供什么来停止 @Scheduled 任务?

原文由 Sachin Gupta 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

选项 1:使用后处理器

提供 ScheduledAnnotationBeanPostProcessor 并显式调用 postProcessBeforeDestruction(Object bean, String beanName) ,为其调度应停止的 bean。

选项 2:维护目标 bean 到其 Future 的映射

private final Map<Object, ScheduledFuture<?>> scheduledTasks =
        new IdentityHashMap<>();

@Scheduled(fixedRate = 2000)
public void fixedRateJob() {
    System.out.println("Something to be done every 2 secs");
}

@Bean
public TaskScheduler poolScheduler() {
    return new CustomTaskScheduler();
}

class CustomTaskScheduler extends ThreadPoolTaskScheduler {

    @Override
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) {
        ScheduledFuture<?> future = super.scheduleAtFixedRate(task, period);

        ScheduledMethodRunnable runnable = (ScheduledMethodRunnable) task;
        scheduledTasks.put(runnable.getTarget(), future);

        return future;
    }

    @Override
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period) {
        ScheduledFuture<?> future = super.scheduleAtFixedRate(task, startTime, period);

        ScheduledMethodRunnable runnable = (ScheduledMethodRunnable) task;
        scheduledTasks.put(runnable.getTarget(), future);

        return future;
    }
}

当必须停止对 bean 的调度时,您可以查找映射以获取对应的 Future 并明确取消它。

原文由 Mahesh 发布,翻译遵循 CC BY-SA 4.0 许可协议

这是一个示例,我们可以在其中停止、启动并列出所有计划运行的任务:

 @RestController
@RequestMapping("/test")
public class TestController {

private static final String SCHEDULED_TASKS = "scheduledTasks";

@Autowired
private ScheduledAnnotationBeanPostProcessor postProcessor;

@Autowired
private ScheduledTasks scheduledTasks;

@Autowired
private ObjectMapper objectMapper;

@GetMapping(value = "/stopScheduler")
public String stopSchedule(){
    postProcessor.postProcessBeforeDestruction(scheduledTasks, SCHEDULED_TASKS);
    return "OK";
}

@GetMapping(value = "/startScheduler")
public String startSchedule(){
    postProcessor.postProcessAfterInitialization(scheduledTasks, SCHEDULED_TASKS);
    return "OK";
}

@GetMapping(value = "/listScheduler")
public String listSchedules() throws JsonProcessingException{
    Set<ScheduledTask> setTasks = postProcessor.getScheduledTasks();
    if(!setTasks.isEmpty()){
        return objectMapper.writeValueAsString(setTasks);
    }else{
        return "No running tasks !";
    }
 }
}

原文由 Abder KRIMA 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题