Как перезапустить запланированную задачу во время выполнения с помощью аннотации EnableScheduling в spring?
Я изучаю, как изменить частоту задания во время выполнения с помощью Java 8 и spring. Этот вопрос был очень полезен, но он не полностью решил мою проблему.
Теперь я могу настроить дату, когда нужно выполнить следующую работу. Но если установить задержку на 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
- Создайте синглтон bean, который получает введенный
TaskScheduler
. Это будет содержать переменные состояния ScheduledFuture
s, например private ScheduledFuture job1;
- При развертывании загрузите из баз данных все данные расписания и запустите задания, заполнив все переменные состояния, такие как
job1
.
- При изменении данных планирования cancel соответствующий
Future
(например, job1
), а затем запустите его снова с помощью нового планирование данных.
Основная идея здесь - получить контроль над Future
по мере их создания, чтобы сохранить их в некоторых переменных состояния, так что когда что-то в планировании данных изменится, вы можете отменить их.
Вот рабочий код:
applicationContext.xml
<task:annotation-driven />
<task:scheduler id="infScheduler" pool-size="10"/>
Синглетный bean, содержащий 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);
}
}
}
Ответ 2
Один простой подход заключается только в том, чтобы добавлять новые задачи, а не пытаться отменить или перезапустить планировщик.
При каждом изменении конфигурации просто добавьте новую задачу с новой конфигурацией.
Затем, всякий раз, когда запускается задача, она должна сначала проверить состояние (путем запроса базы данных или поиска на параллельной карте или что-то еще), чтобы решить, является ли она последней версией. Если да, то это должно продолжаться. В противном случае он должен немедленно прекратиться.
Единственным недостатком является то, что если вы часто меняете конфигурацию задания по сравнению с тем, как часто они запускаются, то, конечно, список запланированных задач будет продолжать расти в памяти.