Java Academy · Lektion

ScheduledExecutorService für wiederkehrende Aufgaben

Planen Sie Aufgaben in festen Intervallen oder mit festen Verzögerungen für Polling und Wartungsarbeiten im Hintergrund.

Lektion 4 von 413 Schritte

ScheduledExecutorService für wiederkehrende Aufgaben ist eine kostenlose Java Academy-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Java Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.

Warum ScheduledExecutorService?

ScheduledExecutorService erweitert ExecutorService um die Planung von Aufgaben zu unterstützen. Es ersetzt die älteren Klassen Timer/TimerTask durch einen threadpoolbasierten und ausnahmesicheren Scheduler.

import java.util.concurrent.*;

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);

// One-shot delay
scheduler.schedule(
    () -> System.out.println("Runs once after 3 seconds"),
    3, TimeUnit.SECONDS
);

// Don't forget to shut down eventually:
// scheduler.shutdown();

schedule: Einmalige Verzögerung

schedule(task, delay, unit) führt die Aufgabe nach der angegebenen Verzögerung einmal aus. Funktioniert sowohl mit Runnable als auch mit Callable:

ScheduledExecutorService s = Executors.newScheduledThreadPool(1);

// Runnable:
ScheduledFuture<?> sf1 = s.schedule(
    () -> System.out.println("Runnable fired!"), 2, TimeUnit.SECONDS);

// Callable:
ScheduledFuture<Integer> sf2 = s.schedule(
    () -> { System.out.println("Callable fired!"); return 42; },
    2, TimeUnit.SECONDS);

System.out.println(sf2.get()); // 42 (after 2 seconds)

scheduleAtFixedRate

scheduleAtFixedRate(task, initialDelay, period, unit) führt die Aufgabe wiederholt mit einer festen Rate aus. Wenn eine Aufgabe länger als die Periode dauert, beginnt die nächste Ausführung unmittelbar nach ihrem Abschluss, ohne Überlappung.

ScheduledExecutorService s = Executors.newScheduledThreadPool(1);
AtomicInteger count = new AtomicInteger();

ScheduledFuture<?> sf = s.scheduleAtFixedRate(
    () -> System.out.println("Tick " + count.incrementAndGet()),
    0,   // initial delay
    1,   // period
    TimeUnit.SECONDS
);

Thread.sleep(5000);
sf.cancel(false); // stop after 5 ticks
s.shutdown();

scheduleWithFixedDelay

scheduleWithFixedDelay(task, initialDelay, delay, unit) wartet nach dem Abschluss jeder Aufgabe die angegebene Verzögerung, bevor die nächste gestartet wird. Geeignet für Polling, wenn die Aufgabendauer variiert.

s.scheduleWithFixedDelay(
    () -> {
        System.out.println("Polling... " + Instant.now());
        // variable-length polling task
    },
    0,  // no initial delay
    5,  // 5-second gap AFTER each completion
    TimeUnit.SECONDS
);
// Next execution = task end + 5 seconds (not task start)

Feste Rate vs. feste Verzögerung

Der entscheidende Unterschied:

  • scheduleAtFixedRate: nächster Start = letzter Start + Periode (zeitlich driftfrei)
  • scheduleWithFixedDelay: nächster Start = letztes Ende + Verzögerung (garantierter Abstand zwischen den Ausführungen)

Verwenden Sie fixedRate für Heartbeats und fixedDelay für Polling, wenn die Aufgabendauer variiert.

ScheduledFuture: Abbrechen

schedule/scheduleAtFixedRate/scheduleWithFixedDelay geben ein ScheduledFuture zurück. Rufen Sie cancel(false) auf, um zukünftige Ausführungen zu stoppen, ohne die gerade laufende Ausführung zu unterbrechen:

ScheduledFuture<?> sf = scheduler.scheduleAtFixedRate(
    () -> System.out.println("Heartbeat"), 0, 1, TimeUnit.SECONDS);

// Cancel after 5 seconds
scheduler.schedule(() -> sf.cancel(false), 5, TimeUnit.SECONDS);

Ausnahmen in geplanten Aufgaben behandeln

Wenn eine geplante Aufgabe eine nicht abgefangene Ausnahme auslöst, beendet der Scheduler die wiederkehrende Ausführung stillschweigend – es finden keine weiteren Ausführungen statt. Verwenden Sie stets try-catch:

scheduler.scheduleAtFixedRate(() -> {
    try {
        // risky work
        if (Math.random() < 0.3) throw new RuntimeException("transient");
        System.out.println("Success");
    } catch (Exception e) {
        System.err.println("Task error: " + e.getMessage());
        // task continues to run on next interval
    }
}, 0, 2, TimeUnit.SECONDS);

Praxis: Cache aktualisieren

Verwenden Sie eine geplante Aufgabe, um einen Cache regelmäßig zu aktualisieren:

class PriceCache {
    private volatile Map<String, Double> prices = new HashMap<>();
    
    PriceCache(ScheduledExecutorService scheduler) {
        scheduler.scheduleAtFixedRate(this::refresh, 0, 30, TimeUnit.SECONDS);
    }
    
    private void refresh() {
        System.out.println("Refreshing prices...");
        // prices = fetchFromDatabase();
    }
    
    Double getPrice(String symbol) { return prices.get(symbol); }
}

Praxis: Wiederholungsversuche mit Backoff

Implementieren Sie Wiederholungsversuche mit exponentiellem Backoff mithilfe geplanter Aufgaben:

void retryWithBackoff(Runnable task, int maxRetries, ScheduledExecutorService s) {
    AtomicInteger attempts = new AtomicInteger(0);
    long[] delay = {1}; // seconds
    
    Runnable wrapper = new Runnable() {
        public void run() {
            try {
                task.run();
            } catch (Exception e) {
                int n = attempts.incrementAndGet();
                if (n < maxRetries) {
                    delay[0] *= 2;
                    s.schedule(this, delay[0], TimeUnit.SECONDS);
                } else System.err.println("Max retries reached");
            }
        }
    };
    s.execute(wrapper);
}

Überwachung: getDelay und getQueue

Überprüfen Sie den Zustand des Schedulers:

ScheduledFuture<?> sf = scheduler.schedule(() -> {}, 10, TimeUnit.SECONDS);
System.out.println("Delay remaining: " + sf.getDelay(TimeUnit.SECONDS) + "s");

// ThreadPoolExecutor provides queue inspection:
if (scheduler instanceof ScheduledThreadPoolExecutor ste) {
    System.out.println("Queue size: " + ste.getQueue().size());
}

Herunterfahren und Abarbeiten

Legen Sie beim Herunterfahren fest, ob geplante Aufgaben weiterhin ausgeführt werden sollen:

ScheduledThreadPoolExecutor ste = (ScheduledThreadPoolExecutor)
    Executors.newScheduledThreadPool(2);

// Cancel scheduled tasks on shutdown (default: false = they run)
ste.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
ste.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);

ste.shutdown();

Kurzer Test

Eine mit scheduleAtFixedRate(..., 1, TimeUnit.SECONDS) geplante Aufgabe benötigt 3 Sekunden für ihre Ausführung. Wie behandelt der Scheduler dies?

Zusammenfassung: ScheduledExecutorService

Wichtige Erkenntnisse:

  • schedule() — einmalige Ausführung mit Verzögerung
  • scheduleAtFixedRate() — driftfreies Timing (von Start zu Start)
  • scheduleWithFixedDelay() — garantierter Abstand (von Ende zu Start)
  • Unbehandelte Ausnahmen beenden wiederkehrende Aufgaben stillschweigend — verwenden Sie immer try-catch
  • Abbrechen mit ScheduledFuture.cancel(false)
Kostenlos starten

Lerne Java mit einem KI-Tutor — kostenlos

Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.

Kurse
104
Lektionen
374

Häufig gestellte Fragen

Ist die Lektion „ScheduledExecutorService für wiederkehrende Aufgaben“ kostenlos?

Ja — der vollständige Text von „ScheduledExecutorService für wiederkehrende Aufgaben“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Java Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „ScheduledExecutorService für wiederkehrende Aufgaben“?

Planen Sie Aufgaben in festen Intervallen oder mit festen Verzögerungen für Polling und Wartungsarbeiten im Hintergrund. Du übst Java Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Java Academy zu starten?

Keine Vorkenntnisse erforderlich. Java Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.

Wie lange dauert die Lektion „ScheduledExecutorService für wiederkehrende Aufgaben“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Java Academy-Lektion Code schreiben und ausführen?

Ja. Jede Java Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. ExecutorService und Thread-Pool-Typen
  2. Aufgaben übermitteln: Runnable vs. Callable
  3. Future und Fehlerbehandlung
  4. ScheduledExecutorService für wiederkehrende Aufgaben
← Zurück zu Java Academy