ExecutorService und Thread-Pool-Typen
Erstellen Sie feste, zwischengespeicherte, einzelne und geplante Thread-Pools und verstehen Sie, wann welcher Typ sinnvoll ist.
ExecutorService und Thread-Pool-Typen ist eine kostenlose Java Academy-Lektion auf CoddyKit. Dies ist Lektion 1 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 Thread-Pools verwenden?
Für jede Aufgabe einen neuen Thread zu erstellen, ist teuer – das Erstellen und Zerstören von Threads verursacht zusätzlichen Aufwand. Ein Thread-Pool verwendet eine feste Gruppe von Threads wieder, um viele Aufgaben auszuführen. Dadurch wird der Aufwand reduziert und der Ressourcenverbrauch kontrolliert.
import java.util.concurrent.*;
// Bad practice: new thread per task
new Thread(() -> System.out.println("task")).start();
// Better: reuse threads from a pool
ExecutorService pool = Executors.newFixedThreadPool(4);
pool.submit(() -> System.out.println("task from pool"));
pool.shutdown();newFixedThreadPool
Erstellt einen Pool mit genau N Threads. Zusätzliche Aufgaben werden in eine Warteschlange gestellt, bis ein Thread verfügbar ist. Geeignet, wenn Sie den gewünschten Grad an Parallelität kennen.
ExecutorService pool = Executors.newFixedThreadPool(4);
for (int i = 0; i < 10; i++) {
final int taskId = i;
pool.submit(() -> {
System.out.println("Task " + taskId + " on " + Thread.currentThread().getName());
});
}
pool.shutdown();
pool.awaitTermination(10, TimeUnit.SECONDS);newCachedThreadPool
Erstellt Threads bei Bedarf und verwendet untätige Threads wieder. Threads, die 60 Sekunden lang untätig waren, werden beendet. Geeignet für viele kurzlebige Aufgaben, aber riskant bei lang laufenden oder unbegrenzt vielen Aufgaben, da der Speicher erschöpft werden kann.
ExecutorService cached = Executors.newCachedThreadPool();
for (int i = 0; i < 100; i++) {
cached.submit(() -> {
// quick task
double result = Math.sqrt(Math.random());
});
}
cached.shutdown();newSingleThreadExecutor
Ein Pool mit genau einem Thread. Die Aufgaben werden in der Reihenfolge ihrer Übergabe nacheinander ausgeführt. Geeignet, um den Zugriff auf eine gemeinsam genutzte Ressource zu serialisieren.
ExecutorService single = Executors.newSingleThreadExecutor();
single.submit(() -> System.out.println("Task 1"));
single.submit(() -> System.out.println("Task 2"));
single.submit(() -> System.out.println("Task 3"));
// Always prints: Task 1, Task 2, Task 3 (sequential)
single.shutdown();newScheduledThreadPool
Unterstützt geplante und wiederkehrende Aufgaben. Verwenden Sie ihn für Polling, Wiederholungsversuche und Hintergrundwartung.
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
// One-shot delay
scheduler.schedule(() -> System.out.println("Delayed!"),
3, TimeUnit.SECONDS);
// Fixed rate (every 2 seconds)
scheduler.scheduleAtFixedRate(
() -> System.out.println("Tick"),
0, 2, TimeUnit.SECONDS);
// Run later: scheduler.shutdown();VirtualThreadExecutor (Java 21+)
Java 21 führt virtuelle Threads ein – sie sind leichtgewichtig und kostengünstig zu erstellen. Verwenden Sie Executors.newVirtualThreadPerTaskExecutor() für Workloads mit hohem I/O-Anteil:
// Java 21+
try (var exec = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 10_000; i++) {
final int id = i;
exec.submit(() -> {
Thread.sleep(100); // blocks without tying up OS thread
System.out.println("vthread " + id);
});
}
} // auto-shutdownDen richtigen Pool auswählen
Richtlinien:
- CPU-bound-Aufgaben: Fixed Pool mit N = Anzahl der CPU-Kerne
- I/O-bound-Aufgaben: Cached Pool oder virtuelle Threads
- Sequenzielle Aufgaben: Single-Thread-Executor
- Geplante/wiederkehrende Aufgaben: Scheduled Thread Pool
int cores = Runtime.getRuntime().availableProcessors();
ExecutorService cpuPool = Executors.newFixedThreadPool(cores);
System.out.println("Pool size: " + cores);Benutzerdefinierter ThreadPoolExecutor
Für eine detaillierte Kontrolle erstellen Sie direkt einen ThreadPoolExecutor:
ThreadPoolExecutor tpe = new ThreadPoolExecutor(
2, // corePoolSize
10, // maximumPoolSize
60L, // keepAliveTime
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100), // work queue
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy() // rejection policy
);
tpe.submit(() -> System.out.println("Custom pool task"));
tpe.shutdown();Geordnetes Herunterfahren
Fahren Sie den ExecutorService stets herunter, um Threads freizugeben. shutdown() nimmt keine neuen Aufgaben mehr an, führt aber bereits eingereihte Aufgaben vollständig aus. shutdownNow() versucht, laufende Aufgaben abzubrechen.
ExecutorService pool = Executors.newFixedThreadPool(4);
// ... submit tasks ...
pool.shutdown(); // no new tasks
try {
if (!pool.awaitTermination(30, TimeUnit.SECONDS)) {
pool.shutdownNow(); // force cancel
}
} catch (InterruptedException e) {
pool.shutdownNow();
Thread.currentThread().interrupt();
}ExecutorService als AutoCloseable (Java 19+)
Ab Java 19 implementiert ExecutorService AutoCloseable. Verwenden Sie try-with-resources für ein automatisches Herunterfahren:
// Java 19+ (preview), Java 21 stable
try (ExecutorService pool = Executors.newFixedThreadPool(4)) {
pool.submit(() -> System.out.println("task"));
} // pool.close() called: waits for tasks then shuts downAblehnungsrichtlinien
Wenn der Pool ausgelastet ist (alle Threads beschäftigt, Warteschlange voll), verarbeitet die Ablehnungsrichtlinie den Überlauf:
- AbortPolicy (Standard): löst
RejectedExecutionExceptionaus - CallerRunsPolicy: Der aufrufende Thread führt die Aufgabe aus
- DiscardPolicy: Verwirft die Aufgabe stillschweigend
- DiscardOldestPolicy: Verwirft die älteste Aufgabe in der Warteschlange
Kurzer Test
Sie haben eine CPU-bound-Aufgabe, die umfangreiche Berechnungen durchführt. Wie viele Threads sollte Ihr Fixed Thread Pool haben?
Zusammenfassung: ExecutorService und Thread-Pools
Die wichtigsten Punkte:
- Fixed Pool: feste Anzahl N von Threads; zusätzliche Aufgaben werden eingereiht
- Cached Pool: wächst bei Bedarf; untätige Threads laufen nach 60 Sekunden ab
- Single Thread: Reihenfolge der seriellen Ausführung ist garantiert
- Scheduled Pool: verzögerte und wiederkehrende Aufgaben
- Stets shutdown() aufrufen; awaitTermination() für ein sauberes Beenden verwenden
Häufig gestellte Fragen
Ist die Lektion „ExecutorService und Thread-Pool-Typen“ kostenlos?
Ja — der vollständige Text von „ExecutorService und Thread-Pool-Typen“ 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 „ExecutorService und Thread-Pool-Typen“?
Erstellen Sie feste, zwischengespeicherte, einzelne und geplante Thread-Pools und verstehen Sie, wann welcher Typ sinnvoll ist. 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 1 von 4.
Wie lange dauert die Lektion „ExecutorService und Thread-Pool-Typen“?
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
- ExecutorService und Thread-Pool-Typen
- Aufgaben übermitteln: Runnable vs. Callable
- Future und Fehlerbehandlung
- ScheduledExecutorService für wiederkehrende Aufgaben