Parallelität und Multithreading in Java: Ein vollständiger Leitfaden

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Parallelität und Multithreading in Java: Von den Grundlagen bis zu fortgeschrittenen Techniken



Moderne Anwendungen erfordern maximale Leistung. In Java sind Parallelität und Multithreading die wichtigsten Werkzeuge für die effiziente Nutzung von Mehrkernprozessoren. In diesem Artikel werden wir uns ansehen, wie man richtig mit Threads, Synchronisation und modernen Parallelitätsutilities arbeitet.



Was ist Multithreading in Java?

Multithreading ist die Fähigkeit eines Programms, mehrere Aufgaben gleichzeitig auszuführen. In Java ist jeder Thread ein leichtgewichtiger Prozess mit einem eigenen Aufrufstapel. Die Hauptvorteile sind:

  • Leistungssteigerung durch parallele Ausführung
  • Reaktionsfähigere Benutzeroberfläche
  • Effiziente Nutzung der CPU-Ressourcen


Thread-Erstellung: Zwei Ansätze

In Java gibt es zwei Hauptmethoden, um einen Thread zu erstellen:



1. Vererbung von der Klasse Thread

public class MyThread extends Thread {    @Override    public void run() {        System.out.println("Thread wird ausgeführt: " + Thread.currentThread().getName());    }

public static void main(String[] args) { MyThread thread = new MyThread(); thread.start(); // Thread starten }}


2. Implementierung des Runnable-Interfaces

public class Task implements Runnable {    @Override    public void run() {        System.out.println("Aufgabe wird im Thread ausgeführt: " + Thread.currentThread().getName());    }

public static void main(String[] args) { Thread thread = new Thread(new Task()); thread.start(); }}

Es wird empfohlen, Runnable zu verwenden, da es die Möglichkeit der Vererbung anderer Klassen nicht einschränkt.



Thread-Synchronisation: Race Conditions vermeiden

Wenn mehrere Threads auf gemeinsame Daten zugreifen, treten Synchronisationsprobleme auf. Betrachten wir ein klassisches Beispiel – einen Zähler:



public class Counter {    private int count = 0;

public synchronized void increment() { count++; }

public synchronized int getCount() { return count; }}

Das Schlüsselwort synchronized garantiert, dass nur ein Thread die Methode gleichzeitig ausführen kann. Eine Alternative ist die Verwendung von Lock aus dem Paket java.util.concurrent.locks.



Deadlock: Wie man gegenseitige Blockaden vermeidet

Ein Deadlock tritt auf, wenn zwei Threads auf die Freigabe der Ressourcen des jeweils anderen warten. Beispiel:

public class DeadlockExample {    private final Object lock1 = new Object();    private final Object lock2 = new Object();

public void method1() { synchronized (lock1) { synchronized (lock2) { // Kritischer Abschnitt } } }

public void method2() { synchronized (lock2) { synchronized (lock1) { // Kritischer Abschnitt } } }}

Um einen Deadlock zu vermeiden, sollten Sie Sperren immer in derselben Reihenfolge anfordern oder tryLock() mit einem Timeout verwenden.



ExecutorService: Verwaltung eines Thread-Pools

Das manuelle Erstellen von Threads ist ineffizient. Java bietet ExecutorService zur Verwaltung eines Thread-Pools:



import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;

public class ThreadPoolExample { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(4);

for (int i = 0; i < 10; i++) { executor.submit(() -> { System.out.println("Wird ausgeführt in: " + Thread.currentThread().getName()); }); }

executor.shutdown(); // Beendigung nach Ausführung aller Aufgaben }}

Die wichtigsten

Blogs

Buchempfehlungen