Wie ändere ich @Scheduled fixedDelay von Spring zur Laufzeit?

Lesezeit: 6 Minuten

Wie andere ich @Scheduled fixedDelay von Spring zur Laufzeit
jsf

Ich muss einen Batch-Job in einem festen Intervall ausführen und die Möglichkeit haben, die Zeit dieses Batch-Jobs zur Laufzeit zu ändern. Dafür bin ich auf gestoßen @Scheduled Anmerkung unter Spring Framework bereitgestellt. Aber ich bin mir nicht sicher, wie ich den Wert von fixedDelay zur Laufzeit ändern würde. Ich habe etwas gegoogelt, aber nichts brauchbares gefunden.

  • Ich sehe, Sie haben die beste Antwort akzeptiert, aber ich sehe immer noch, dass es einige ungelöste Probleme gab. Wurde das NPE-Problem gelöst? Kannst du die ganze Lösung dafür posten? Prost

    – Despot

    22. November 2013 um 9:57 Uhr

  • Mögliches Duplikat von Scheduling a job with Spring programmatically (mit dynamisch festgelegter fixedRate)

    – Steve Kammern

    5. Oktober 2015 um 9:54 Uhr

  • @jsf Sie können meine Antwort hier sehen: stackoverflow.com/a/51333059/2590960

    – grep

    13. Juli 2018 um 23:36 Uhr

Wie andere ich @Scheduled fixedDelay von Spring zur Laufzeit
Bohemien

Im Spring Boot können Sie eine Anwendungseigenschaft direkt verwenden!

Zum Beispiel:

@Scheduled(fixedDelayString = "${my.property.fixed.delay.seconds}000")
private void process() {
    // your impl here
}

Beachten Sie, dass Sie auch einen Standardwert haben können, falls die Eigenschaft nicht definiert ist, z. B. um einen Standardwert von “60” (Sekunden) zu haben:

@Scheduled(fixedDelayString = "${my.property.fixed.delay.seconds:60}000")

Andere Dinge, die ich entdeckt habe:

  • die Methode muss void sein
  • Die Methode darf keine Parameter haben
  • die Methode kann sein private

Ich fand in der Lage zu verwenden private Sichtbarkeit handlich und verwendet es auf diese Weise:

@Service
public class MyService {
    public void process() {
        // do something
    }

    @Scheduled(fixedDelayString = "${my.poll.fixed.delay.seconds}000")
    private void autoProcess() {
        process();
    }
}

Sein privatekann die geplante Methode für Ihren Dienst lokal sein und nicht Teil der API Ihres Dienstes werden.

Auch dieser Ansatz ermöglicht die process() Methode, um einen Wert zurückzugeben, der a @Scheduled Methode möglicherweise nicht. Zum Beispiel Ihre process() Methode kann so aussehen:

public ProcessResult process() {
    // do something and collect information about what was done
    return processResult; 
}

um einige Informationen darüber bereitzustellen, was während der Verarbeitung passiert ist.

  • Danke, fixedDelayString habe ich gesucht

    – ziemlich leer

    3. Februar 2016 um 9:13 Uhr

  • Gute Antwort. Funktioniert wie beschrieben.

    – Blitz

    6. September 2016 um 11:45 Uhr

  • @Bohemain Danke für die Lösung, aber wie wird das fixedDelay zur Laufzeit aktualisiert?

    – Tonbänke

    27. September 2016 um 2:53 Uhr

  • @KuraiBankusu ist eingestellt auf Anlaufen Zeit durch Verwendung einer umgebungsspezifischen Konfigurations-/Eigenschaftsdatei. Sie können es nach dem Start nicht ändern, aber es gibt selten einen Anwendungsfall dafür. Wenn Sie es wirklich nach dem Start ändern müssen, ändern Sie die Konfiguration und starten Sie neu!

    – Böhmisch

    27. September 2016 um 2:56 Uhr


  • Dies ist keine nützliche Antwort. Der OP hat nachgefragt at runtimeund Ihre Lösung erfordert einen Neustart?

    – dnang

    2. November 2017 um 8:41 Uhr


1647164227 531 Wie andere ich @Scheduled fixedDelay von Spring zur Laufzeit
Ach

Sie können eine verwenden Trigger um die nächste Ausführungszeit dynamisch einzustellen.

Weitere Informationen finden Sie in meiner Antwort auf Programmatisches Planen eines Auftrags mit Spring.

  • FYI – Hat dir einen Kommentar hinterlassen NullPointerException Fehler im Code bemerkt.

    – jsf

    6. März 2013 um 17:03 Uhr

  • Gibt es eine Möglichkeit, den aktuellen Trigger zu unterbrechen und seinen Wert zu ändern, während er schläft?

    – jsf

    6. März 2013 um 17:53 Uhr

  • Sie können auch meine Antwort sehen: stackoverflow.com/a/51333059/2590960

    – grep

    13. Juli 2018 um 23:34 Uhr

Wie andere ich @Scheduled fixedDelay von Spring zur Laufzeit
grep

create interface , etwa so:

    public abstract class DynamicSchedule{
        /**
         * Delays scheduler
         * @param milliseconds - the time to delay scheduler.
         */
        abstract void delay(Long milliseconds);

        /**
         * Decreases delay period
         * @param milliseconds - the time to decrease delay period.
         */
        abstract void decreaseDelayInterval(Long milliseconds);

        /**
         * Increases delay period
         * @param milliseconds - the time to increase dela period
        */
        abstract void increaseDelayInterval(Long milliseconds);
}

Als Nächstes implementieren wir die Trigger-Schnittstelle, die sich unter org.springframework.scheduling im spring-context-Projekt befindet.

import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;

import java.util.Date;
import java.util.concurrent.ScheduledFuture;

public class CustomDynamicSchedule extends DynamicSchedule implements Trigger {

    private TaskScheduler taskScheduler;
    private ScheduledFuture<?> schedulerFuture;

    /**
     * milliseconds
     */
    private long delayInterval;

    public CustomDynamicSchedule(TaskScheduler taskScheduler) {
        this.taskScheduler = taskScheduler;
    }


    @Override
    public void increaseDelayInterval(Long delay) {
        if (schedulerFuture != null) {
            schedulerFuture.cancel(true);
        }
        this.delayInterval += delay;
        schedulerFuture = taskScheduler.schedule(() -> { }, this);
    }

    @Override
    public void decreaseDelayInterval(Long delay) {
        if (schedulerFuture != null) {
            schedulerFuture.cancel(true);
        }
        this.delayInterval -= delay;
        schedulerFuture = taskScheduler.schedule(() -> { }, this);
    }

    @Override
    public void delay(Long delay) {
        if (schedulerFuture != null) {
            schedulerFuture.cancel(true);
        }
        this.delayInterval = delay;
        schedulerFuture = taskScheduler.schedule(() -> { }, this);
    }

    @Override
    public Date nextExecutionTime(TriggerContext triggerContext) {
        Date lastTime = triggerContext.lastActualExecutionTime();
        return (lastTime == null) ? new Date() : new Date(lastTime.getTime() + delayInterval);
    }
}

jetzt Konfiguration:

@Configuration
public class DynamicSchedulerConfig {
    @Bean
    public CustomDynamicSchedule getDynamicScheduler() {
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        threadPoolTaskScheduler.initialize();
        return  new CustomDynamicSchedule(threadPoolTaskScheduler);
    }
}

und Verwendung:

@EnableScheduling
@Component
public class TestSchedulerComponent {

    @Autowired
    private CustomDynamicSchedule dynamicSchedule;

    @Scheduled(fixedDelay = 5000)
    public void testMethod() {
        dynamicSchedule.delay(1000l);
        dynamicSchedule.increaseDelayInterval(9000l);
        dynamicSchedule.decreaseDelayInterval(5000l);
    }

}

  • Was bedeutet diese Syntax? () -> {}

    – Aliuk

    12. September 2018 um 10:12 Uhr

  • Die Antwort auf meinen Kommentar ist in dieser anderen Frage: stackoverflow.com/questions/52292953/meaning-of-lambda-in-java

    – Aliuk

    12. September 2018 um 10:47 Uhr

  • Sie können die Runnable-Klasse bestehen. Zum Beispiel können Sie die Klasse übergeben, die protokolliert, wann die Zeit geändert wird.

    – grep

    12. September 2018 um 10:55 Uhr

  • @grep: Ich habe deine Antwort verwendet, aber sie funktioniert bei mir nicht. Ich habe Folgendes gedruckt: System.out.println (letztes Mal); und wird null.

    – Mayank bisht

    22. Mai 2019 um 7:40 Uhr


  • @grep: Dein Code funktioniert bei mir nicht, kannst du mir bitte helfen?

    – Mayank bisht

    26. Mai 2019 um 6:33 Uhr

1647164229 907 Wie andere ich @Scheduled fixedDelay von Spring zur Laufzeit
Sagar Ahuja

Sie können dafür auch die Spring Expression Language (SpEL) verwenden.

@Scheduled(fixedDelayString = "#{@applicationPropertyService.getApplicationProperty()}")
public void getSchedule(){
   System.out.println("in scheduled job");
}

@Service
public class ApplicationPropertyService {

    public String getApplicationProperty(){
        //get your value here
        return "5000";
    }
}

AFAIK Mit der Spring-API können Sie nicht auf die Interna zugreifen, die Sie zum Ändern des Triggers benötigen. Aber Sie könnten die Beans stattdessen auch manuell konfigurieren:

<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
    <property name="jobDetail" ref="jobDetail" />
    <property name="startDelay" value="10000" />
    <property name="repeatInterval" value="50000" />
</bean>

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
        <list>
            <ref bean="simpleTrigger" />
        </list>
    </property>
</bean>

Dann wie in SchedulerFactoryBean dokumentiert:

Verwenden Sie für die dynamische Registrierung von Jobs zur Laufzeit eine Bean-Referenz zu dieser SchedulerFactoryBean, um direkten Zugriff auf den Quartz-Scheduler zu erhalten (org.quartz.Scheduler). Damit können Sie neue Jobs und Trigger erstellen sowie den gesamten Scheduler steuern und überwachen.

1647164230 754 Wie andere ich @Scheduled fixedDelay von Spring zur Laufzeit
egelew

Ich habe mich mit dem gleichen Problem beschäftigt. Wir hatten die Anforderung, den Cron-Ausdruck zur Laufzeit zu ändern und den Dienst neu zu planen. Also sollte es geben:

  • keine Neukompilierung
  • keine Umschichtung
  • kein neustart

der Bewerbung. Ich habe alle gängigen Lösungen inspiziert, aber nur 2 davon erfüllen alle Anforderungen.

  • Implementieren SchedulingConfigurer wie ach vorgeschlagen
  • Verwenden Sie eine benutzerdefinierte Lösung wie beschrieben Hier

Der Nachteil des SchedulingConfigurer-Ansatzes ist, dass dies der Fall ist Pull-basiert, dh die Planungskonfiguration wird jedes Mal abgerufen, wenn die Geschäftslogik des Diensts ausgeführt wird. Dies ist im Allgemeinen keine schlechte Sache, aber wenn die Konfiguration selten geändert wird und das Ausführungsintervall kurz ist, gibt es viele unnötige Anfragen.

Der Nachteil der individuelle Lösung ist, dass es ein bisschen mehr Codierung erfordert, aber es ist Push-basiert und reagiert auf Konfigurationsänderungen, sodass keine unnötigen Anfragen/Aufrufe durchgeführt werden.

996920cookie-checkWie ändere ich @Scheduled fixedDelay von Spring zur Laufzeit?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy