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.
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. –
Können Sie einen Quellcode mit Ihrem Code teilen ?, weil der Code so aussieht, als würde der Code einen einzelnen Thread verwenden. – Makoton
Nur @Async muss mit Zeitplanannotation hinzugefügt werden. –