Parallelität und Multithreading in Swift: 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

Einführung in Concurrency und Multithreading in Swift



Moderne iOS- und macOS-Apps müssen schnell und reaktionsfähig sein. Der Benutzer sollte nicht warten müssen, während ein Bild geladen oder eine komplexe Berechnung durchgeführt wird. Zu diesem Zweck gibt es in Swift Mechanismen für Concurrency und Multithreading. In diesem Artikel werden wir die wichtigsten Konzepte behandeln, angefangen beim klassischen Grand Central Dispatch (GCD) bis hin zum modernen async/await aus Swift Concurrency.



Concurrency ist die Fähigkeit eines Programms, mehrere Aufgaben gleichzeitig auszuführen, indem es zwischen ihnen umschaltet. Multithreading ist eine Implementierung von Concurrency, bei der Aufgaben in verschiedenen Threads des Betriebssystems ausgeführt werden. Swift bietet leistungsstarke und sichere Werkzeuge für die Arbeit mit diesen Konzepten.



1. Grand Central Dispatch (GCD) — Grundlage des Multithreading



Grand Central Dispatch (GCD) ist eine Low-Level-Bibliothek von Apple zur Verwaltung der parallelen Ausführung von Code. Sie basiert auf Warteschlangen (dispatch queues).



Arten von Queues in GCD

  • Serial Queue (serielle Warteschlange) — Aufgaben werden nacheinander in der Reihenfolge ihres Hinzufügens ausgeführt.
  • Concurrent Queue (parallele Warteschlange) — Aufgaben können gleichzeitig auf verschiedenen Threads ausgeführt werden.
  • Main Queue (Hauptwarteschlange) — führt Aufgaben auf dem Hauptthread aus, ist für UI-Updates vorgesehen.
  • Global Queues (globale Warteschlangen) — systemweite parallele Warteschlangen mit unterschiedlichen Prioritäten (QoS).


Beispiel: Ausführen einer Aufgabe im Hintergrund und Aktualisieren der UI



import UIKit

class ViewController: UIViewController { @IBOutlet weak var imageView: UIImageView!

func loadImage(from url: URL) { // Wechseln zur Hintergrund-Queue DispatchQueue.global(qos: .background).async { [weak self] in guard let data = try? Data(contentsOf: url), let image = UIImage(data: data) else { return } // Zurück zum Hauptthread für UI-Updates DispatchQueue.main.async { self?.imageView.image = image } } }}


In diesem Beispiel laden wir ein Bild im Hintergrundthread herunter, um die Oberfläche nicht zu blockieren, und aktualisieren dann die UI auf dem Hauptthread.



DispatchGroup zur Synchronisation von Aufgaben



DispatchGroup ermöglicht es, die Ausführung einer Gruppe asynchroner Aufgaben zu verfolgen und eine Aktion nach deren Abschluss auszuführen.



let group = DispatchGroup()

group.enter()fetchData1 { result in print("Daten 1 empfangen") group.leave()}

group.enter()fetchData2 { result in print("Daten 2 empfangen") group.leave()}

group.notify(queue: .main) { print("Alle Daten geladen, UI wird aktualisiert")}


2. OperationQueue — objektorientierter Ansatz



OperationQueue ist eine höherwertige Abstraktion über GCD. Sie arbeitet mit Operation-Objekten, die eine Arbeitseinheit darstellen.



Vorteile von OperationQueue

  • Möglichkeit zum Abbrechen von Aufgaben (cancel).
  • Festlegen von Abhängigkeiten zwischen Operationen (addDependency).
  • Überwachung des Operationsstatus (isFinished, isExecuting, isCancelled).
  • Konfiguration der maximalen Anzahl paralleler Operationen.


Beispiel: Laden mehrerer Bilder



import UIKit

class ImageLoader { private let queue = OperationQueue() func loadImages(from urls: [URL], completion: @escaping ([UIImage]) -> Void) { var images: [UIImage] = [] let completionOperation = BlockOperation { DispatchQueue.main.async { completion(images) } } for url in urls { let o

Blogs

Buchempfehlungen