0

@Scheduling Unter Verwendung der Methode bei @Scheduled laufen (Festsatz = 10000) und durch SchedulingConfigurer Umsetzung @Scheduling Threading einrichtenFrühling Java @Scheduling Konfiguration

@Bean(destroyMethod="shutdown") 
    public Executor taskExecutor() { 
     return Executors.newScheduledThreadPool(10); 
    } 

wenn ich verwendet Thread.sleep oder Lock, kein anderer Thread wird von Executor erstellt, außer Thread.sleep wacht auf oder die Sperre ist deaktiviert.

Kann jemand interne Arbeit erklären, wenn ich 10 Poolgröße habe sie 10 Threads sollte mit einer Rate von 10000 Millisekunden erstellt werden.

Antwort

0

Grundsätzlich solches Verhalten kommt von ScheduledExecutorService Implementierung, die durch Feder intern verwendet wird. Wenn Sie diesen Code ausführen wird erhalten Sie das gleiche Verhalten feststellen:

public static void main(String[] args) throws Exception { 
    ScheduledExecutorService executor = Executors.newScheduledThreadPool(10); 
    executor.schedule(() -> { 
     System.out.println("Running task in thread " + Thread.currentThread().getId()); 
     try { 
      Thread.sleep(Integer.MAX_VALUE); 
     } catch (InterruptedException e) { 
      System.out.println("interrupted while sleeping"); 
     } 
    }, 1000, TimeUnit.MILLISECONDS); 
    Thread.sleep(10000); 
    executor.shutdownNow(); 
} 

Wenn Sie Aufgabe geplant Thread-Pool eintragen mit RunnableScheduledFuture gewickelt ist, die an delayedExecute Methode übergeben wird. Diese Methode fügt die Aufgabe der Aufgabenwarteschlange hinzu und startet einen neuen Mitarbeiter, wenn die aktuelle Anzahl der Mitarbeiter weniger als corePoolSize beträgt. Arbeiter versucht, eine Aufgabe aus der Warteschlange zu bekommen und sie unter Aufruf run Methode zu verarbeiten. Es gibt eine dedizierte DelayedWorkQueue Implementierung, die nur Aufgaben zurückgibt, wenn sie zur Ausführung bereit sind. Hier ist, wie run Methode von RunnableScheduledFuture wie folgt aussieht:

/** 
    * Overrides FutureTask version so as to reset/requeue if periodic. 
    */ 
    public void run() { 
     boolean periodic = isPeriodic(); 
     if (!canRunInCurrentRunState(periodic)) 
      cancel(false); 
     else if (!periodic) 
      ScheduledFutureTask.super.run(); 
     else if (ScheduledFutureTask.super.runAndReset()) { 
      setNextRunTime(); 
      reExecutePeriodic(outerTask); 
     } 
    } 

Wie Sie sehen können es eigentliche Aufgabe Logik in runAndReset aufruft, berechnet die nächste Laufzeit und trägt die gleiche aktualisiert Aufgabe in die Warteschlange wieder (reExecutePeriodic ist fast die gleiche als schedule). Es gibt nur eine einzige periodische Aufgabe für alle Ausführungen, die nach dem Ende der vorherigen Ausführung immer wieder mit aktualisierter Zeit wiederholt wird. Daher führt ein solcher Thread-Pool zu jedem Zeitpunkt nur eine einzige Instanz jedes Task-Typs aus und skaliert nur für unterschiedliche Tasktypen.

Wenn Sie interessant sind, wie Frühling Termine Aufgaben betrachten ScheduledTaskRegistrar Klasse und vor allem bei scheduleFixedDelayTask Methode.

0

Für den Fall, dass Sie threadpool verwenden: Standardmäßig haben Sie 10 Threads in Ihrem Pool (bereits initialisiert). Wenn @scheduled zum ersten Mal ausgeführt wird, wird diese Funktion in einem Thread aus Ihrem Pool ausgeführt (jetzt noch 9 Threads), wenn die Funktion noch beendet ist und @scheduled erneut ausgeführt wird, wird Ihre Funktion in einem anderen Thread von Ihnen ausgeführt Dein Pool, jetzt hast du noch 8 Thread in deinem Pool. (8 im Leerlauf, 2 laufende Threads)

Wenn Sie threadpool nicht verwenden, wird nur ein Thread verwendet.

Feder Dokumentation:

Wenn Sie nicht bieten Attribut einer 'Pool-Größe', den Standard-Thread-Pool nur einen einzigen Thread hat. Es gibt keine andere Konfiguration Optionen für den Scheduler.

https://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/html/scheduling.html

+0

Zustimmen, aber was ich beobachte ist, dass, wenn ich Thread.sleep oder Sperre innerhalb @ Scheduled-Methode für Pool-Größe 10 dann nur ein Mal Thread ausgeführt wird davon dauerhaft gesperrt ist. Nehmen wir an, 1 Thread wird bei der geplanten Methode aus einem Pool von 10 ausgeführt, und 1 Thread bleibt in der Sperre stecken, dann wird kein anderer Thread für die geplante Methodenmethode ausgeführt. alle stecken fest. Selbst wenn ich Schlaf benutzt habe. –

+0

Können Sie einen Quellcode mit Ihrem Code teilen ?, weil der Code so aussieht, als würde der Code einen einzelnen Thread verwenden. – Makoton

+0

Nur @Async muss mit Zeitplanannotation hinzugefügt werden. –

Verwandte Themen