2015-08-12 10 views
12

Badałem, jak zmienić częstotliwość pracy w środowisku wykonawczym z Java 8 i wiosną. This question był bardzo przydatny, ale nie rozwiązało to całkowicie mojego problemu.Jak zrestartować zaplanowane zadanie w środowisku wykonawczym z włączoną adnotacją EnableScheduling na wiosnę?

Mogę teraz skonfigurować datę, kiedy zadanie powinno zostać wykonane dalej. Ale jeśli ustawię opóźnienie na 1 rok, to muszę poczekać 1 rok, zanim nowa konfiguracja zostanie wzięta pod uwagę.

Mój pomysł polegałby na zatrzymaniu zaplanowanego zadania, jeśli wartość konfiguracji zostanie zmieniona (czyli innej klasy). Następnie przeliczyć ponownie przy następnym wykonaniu zadania. Być może jest łatwiejszy sposób robienia tego.

Oto kod, który do tej pory miałem.

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

To byłby to, co chciałbym zrobić.

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

} 
+0

Hej +1 za twoje pytanie. Znasz wiosnę. czy chcesz mi również zilustrować kodowanie sprężynowe? –

Odpowiedz

5
  1. Utwórz fasoli singleton że dostaje wstrzykuje TaskScheduler. Spowoduje to zachowanie wszystkich zmiennych stanu ScheduledFutures, takich jak private ScheduledFuture job1;
  2. Po wdrożeniu, załaduj z baz danych wszystkie dane harmonogramu i uruchom zadania, wypełniając wszystkie zmienne stanu, takie jak job1.
  3. Po zmianie danych planowania, cancel odpowiadające Future (np. job1), a następnie ponowne uruchomienie z nowymi danymi harmonogramu.

Kluczem Chodzi o to, aby uzyskać kontrolę nad Future s, ponieważ są one stworzone tak, aby zapisać je w niektórych zmiennych stanu, tak, że gdy coś się zmian danych szeregowania, można je anulować.

Oto kod roboczych:

applicationContext.xml

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

Singletor fasola, że ​​trzyma w 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); 
       } 
     } 
} 
0

Prostym rozwiązaniem jest zawsze tylko dodać nowe zadania , nie próbować anulować lub zrestartować programu planującego.

Po każdej zmianie konfiguracji wystarczy dodać nowe zadanie z nową konfiguracją.

Następnie, po uruchomieniu zadania, należy najpierw sprawdzić stan (poprzez zapytanie do bazy danych lub wyszukiwanie na współbieżnej mapie lub czymkolwiek), aby zdecydować, czy jest to najnowsza wersja. Jeśli tak, to powinien kontynuować. W przeciwnym razie powinien zakończyć się natychmiast.

Jedynym minusem jest to, że jeśli często zmieniasz konfigurację zadania w porównaniu do tego, jak często działają, to oczywiście lista zaplanowanych zadań będzie nadal rosnąć w pamięci.

Powiązane problemy