Grundlagen des Multithreadings

Codeoptimierung in Java

Pavlos Kosmetatos

Lead Engineer @Wealthyhood

Sequentielle vs. parallele Ausführung

  • Sequentielle Verarbeitung -> Operationen laufen nacheinander ab
  • Parallele Verarbeitung -> mehrere Operationen laufen gleichzeitig

Wie?

  • Moderne CPUs haben mehrere Kerne
  • Thread: die kleinste Einheit der Programmausführung
  • Multithreading verteilt Arbeit auf diese Kerne

Einzel-Threading ist wie eine einspurige Straße: Autos müssen hintereinander fahren. Multithreading ist wie mehrere Spuren: Autos fahren parallel!

Codeoptimierung in Java

Threads verwenden

  • Die Klasse Thread ermöglicht neue Ausführungspfade
  • Jeder Thread kann unabhängig laufen
Runnable task = () -> {
    System.out.println("Processing on thread: " + 
                       Thread.currentThread().getName());
};

Thread thread = new Thread(task);
thread.start();
Processing on thread: Thread-0
Codeoptimierung in Java

Mit mehreren Threads arbeiten

List<Thread> threads = new ArrayList<Thread>();
for (int i = 0; i < 4; i++) {
    Thread thread = new Thread(() -> System.out.println("Processing data on Thread-" + i));
    threads.add(thread);
    thread.start();
}

for (Thread t : threads) {
    t.join(); // Waits for all threads to complete
}
// Processing data on Thread-0
// Processing data on Thread-2
// Processing data on Thread-1
// Processing data on Thread-3
Codeoptimierung in Java

Parallele Streams

  • Streams – Java-8+-Feature für vereinfachte Parallelisierung
  • Erzeugung und Verwaltung von Threads erfolgt automatisch
  • Zwei Arten der Erstellung:
    • collection.parallelStream()
    • Stream.of(...).parallel()
Codeoptimierung in Java

Beispiel: Parallele Streams

// Sequentielle Verarbeitung
List<Integer> result1 = new ArrayList<>();
for (int i = 0; i < numbers.size(); i++) {
    result1.add(numbers.get(i) * 2);
}

// Sequentielle Verarbeitung mit Stream List<Integer> result2 = numbers.stream() .map(n -> n * 2) .collect(Collectors.toList());
// Parallele Verarbeitung mit parallel stream List<Integer> result3 = numbers.parallelStream() .map(n -> n * 2) .collect(Collectors.toList());
Codeoptimierung in Java

Wann parallele Verarbeitung nutzen

  • CPU-intensive Operationen
  • Unabhängige Datenverarbeitung
  • Große Datensammlungen
  • Verfügbare CPU-Kerne > 1
  • Parallelisierungs-Overhead lohnt sich evtl. nicht bei:
    • Kleinen Datensätzen
    • Einfachen Operationen
Codeoptimierung in Java

Zusammenfassung

  • Thread-Klasse zum Erstellen paralleler Ausführungspfade
  • Parallele Streams für vereinfachte Verarbeitung von Collections
  • Nutzen hängt ab von:
    • Art der Workloads
    • Datenmenge
    • Verfügbaren Kernen
Codeoptimierung in Java

Lass uns üben!

Codeoptimierung in Java

Preparing Video For Download...