How to stop a FixedRateScheduledTask in Spring without interrupting a running thread

☆樱花仙子☆ 提交于 2020-05-17 07:07:19

问题


In my SpringBoot application, I have a FixedRateScheduledTask. I want to dynamically change the fixed interval upon a refresh event. Note that depending on the processing time, there could be several parallel threads, thanks to Async. Upon a refresh event, I canceled the current ScheduledTask and re-added a new FixedRateTask with new value for interval. Below is my code

@Configuration
@EnableAsync
@EnableScheduling
public class Scheduler implements SchedulingConfigurer, ApplicationListener<EnvironmentChangeEvent> {

    private final ConfigParams configParams;

    private final MyService myService;

    private ScheduledTask scheduledTask;

    @Autowired
    public Scheduler(ConfigParams schedulerConfigParameters, MyService myService) {
        this.configParams = schedulerConfigParameters;
        this.myService = myService;
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        log.info("configureTasks :: ");
        this.scheduledTask = taskRegistrar.scheduleFixedRateTask(newFixedRateTask());
    }

    public FixedRateTask newFixedRateTask() {
        log.info("newFixedRateTask :: fixedRate {}", configParams.getFixedratedelay());
        return new FixedRateTask(myService::processData,
                configParams.getFixedratedelay(),
                0L);
    }

    @Override
    public void onApplicationEvent(EnvironmentChangeEvent environmentChangeEvent) {
        log.info("onApplicationEvent :: {} ", environmentChangeEvent.getKeys());
        if (environmentChangeEvent.getKeys().contains("scheduled.fixedratedelay")) {
            log.info("config parameter::fixedratedelay::changed");
            this.scheduledTask.cancel(); //Problem. It can interrupt the running task
            new CustomScheduledTaskRegistrar(newFixedRateTask()).afterPropertiesSet();
        }
    }
}

public class CustomScheduledTaskRegistrar extends ContextLifecycleScheduledTaskRegistrar {

    private final FixedRateTask fixedRateTask;

    CustomScheduledTaskRegistrar(FixedRateTask fixedRateTask) {
        this.fixedRateTask = fixedRateTask;
    }

    @Override
    public void afterPropertiesSet() {
        log.info("afterPropertiesSet");
        super.addFixedRateTask(fixedRateTask);
        super.afterSingletonsInstantiated();
    }
}

@Service
public class MyService {

    @Async
    public void processData() {
        log.info("inside processData {} {}", Thread.currentThread().getName(), LocalDateTime.now());
        try {
            Thread.sleep(20000L);
        } catch (InterruptedException e) {
            log.error("InterruptedException ");
        }
    }
}

I could see that ScheduledTask internally uses a ScheduledFuture and cancel() internally calls future.cancel(mayInterruptIfRunning: true). But I want to gracefully stop the task as my task might contain network calls, db operation etc.

Can that be done?

EDIT

Thanks to issue1 and issue2, I changed my approach and used Annotation based scheduling which helps to me gracefully complete existing threads. Sample application is available here

来源:https://stackoverflow.com/questions/61747502/how-to-stop-a-fixedratescheduledtask-in-spring-without-interrupting-a-running-th

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!