Kursinhalt
Multithreading in Java
Multithreading in Java
CopyOnWrite-Sammlung
Wir haben viele synchronisierte Sammlungen zusammen erkundet, und wenn Sie die anderen gemeistert haben, werden Sie diese noch einfacher finden.
Beispiel aus dem echten Leben
Eine Webanwendung, die CopyOnWriteArrayList
verwendet, um Ereignisabonnenten zu speichern. Mehrere Threads können gleichzeitig eine Liste der aktuellen Abonnenten abrufen, um sie über Änderungen zu benachrichtigen, während andere Threads Abonnenten hinzufügen oder entfernen können.
Unterschiede zu anderen Typen
CopyOnWrite
-Sammlungen erstellen bei jeder Änderung eine Kopie der Sammlung, um sicherzustellen, dass Leseoperationen nicht durch Datenänderungen blockiert werden, und bieten somit Threadsicherheit für Lesevorgänge, obwohl Schreiboperationen nicht threadsicher sind, da sie auf einer separaten Kopie der Sammlung erfolgen.
CopyOnWrite Ansichten:
Hinweis
Wie wir auf dem Bild sehen können, erstellen wir beim Hinzufügen eines neuen Elements eine Kopie dieser Datenstruktur. Alle Threads, die zuvor mit dieser Sammlung gearbeitet haben, werden ihre Arbeit ohne Probleme fortsetzen, da diese Änderungen die
CopyOnWrite
-Kopie, die sie verwenden, nicht beeinflussen!
CopyOnWriteArraySet
CopyOnWriteArraySet
ist eine thread-sichere Implementierung eines Sets, die auf CopyOnWriteArrayList
basiert. Sie gewährleistet Thread-Sicherheit, indem bei jeder Änderung, wie dem Hinzufügen oder Entfernen von Elementen, eine neue Kopie des Basissets erstellt wird.
Dieser Ansatz ist besonders nützlich, wenn das Set häufig gelesen und selten geändert wird, da es eine konsistente Ansicht des Sets für alle Threads bietet, ohne dass eine Synchronisation erforderlich ist.
CopyOnWriteArrayList
CopyOnWriteArrayList
ist eine thread-sichere Variante von ArrayList
, die Thread-Sicherheit gewährleistet, indem bei jeder Änderung eine neue Kopie des zugrunde liegenden Arrays erstellt wird.
Dieses Design bietet einen fehlertoleranten Iterator, der keine ConcurrentModificationException
auslöst, da er auf einem Schnappschuss des Arrays arbeitet, der zum Zeitpunkt der Erstellung des Iterators aufgenommen wurde. Es ist am besten geeignet für Situationen, in denen Leseoperationen deutlich häufiger als Schreiboperationen sind, da der Aufwand, das gesamte Array bei jedem Schreibvorgang zu kopieren, erheblich sein kann.
Praktisches Beispiel eines Anwendungsfalls
Methoden der CopyOnWrite-Sammlung
addIfAbsent(E e)
: Fügt ein Element zur Liste hinzu, nur wenn es nicht bereits in der Liste/mehrfach vorhanden ist.
Main
package com.example; import java.util.concurrent.CopyOnWriteArrayList; public class Main { public static void main(String[] args) { CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); list.add("apple"); list.add("banana"); // Attempt to add a duplicate element list.addIfAbsent("apple"); // This will not add "apple" again // Adding a new element list.addIfAbsent("orange"); // This will add "orange" System.out.println(list); // Output: [apple, banana, orange] } }
In diesem Beispiel wird "apple" nicht erneut hinzugefügt, da es bereits in der Liste existiert. Die addIfAbsent()
Methode verhindert doppelte Einträge und bewahrt die Einzigartigkeit der Elemente.
addAllAbsent(Collection<? extends E> c)
: Fügt alle Elemente aus der angegebenen Sammlung zur Liste/mehrfach hinzu und ignoriert bereits vorhandene Elemente.
Main
package com.example; import java.util.Arrays; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; public class Main { public static void main(String[] args) { CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); list.add("apple"); list.add("banana"); List<String> newFruits = Arrays.asList("banana", "cherry", "date"); // Adding elements from the collection, ignoring duplicates list.addAllAbsent(newFruits); System.out.println(list); // Output: [apple, banana, cherry, date] } }
In diesem Beispiel ist "banana" bereits in der Liste vorhanden, daher wird addAllAbsent()
es nicht erneut hinzufügen. Die Methode stellt sicher, dass nur einzigartige Elemente aus der bereitgestellten Sammlung zur Liste hinzugefügt werden.
Hinweis
Alle anderen Methoden der
CopyOnWrite
-Sammlungen sind ähnlich wie die ihrer übergeordneten Sammlungen; sie kopieren einfach den Zustand der Sammlung, wann immer Änderungen vorgenommen werden.
Einschränkungen und Vorteile
😔Einschränkungen:
CopyOnWrite
-Sammlungen haben bemerkenswerte Einschränkungen. Sie verursachen einen Speicheraufwand, da bei jeder Änderung eine neue Kopie der Sammlung erstellt wird, was erheblich sein kann. Dieses Design macht sie weniger geeignet für Szenarien, in denen häufige Datenänderungen erforderlich sind.
💪Vorteile:
Auf der anderen Seite bieten CopyOnWrite
-Sammlungen erhebliche Vorteile. Sie sind hoch effizient beim Lesen von Daten in einer multithreaded Umgebung. Diese Sammlungen funktionieren außergewöhnlich gut in Situationen, in denen Leseoperationen die Schreiboperationen deutlich überwiegen, was sie zu einer ausgezeichneten Wahl für solche Anwendungsfälle macht.
Hinweis
Aufgrund des Kopierens bei jeder Änderung können
CopyOnWrite
-Sammlungen mehr Speicher verbrauchen und sind nicht geeignet für Szenarien mit häufigen Schreiboperationen. Sie sind am effektivsten, wenn Leseoperationen gegenüber Schreiboperationen überwiegen.
1. Was passiert, wenn Sie die Methode addIfAbsent(E e)
in CopyOnWriteArrayList aufrufen?
2. Warum sind CopyOnWrite
-Sammlungen besonders geeignet für Szenarien mit häufigen Lesevorgängen und seltenen Datenänderungen?
Danke für Ihr Feedback!