codestory

Die Anleitung zu Java CopyOnWriteArrayList

  1. CopyOnWriteArrayList

1. CopyOnWriteArrayList

CopyOnWriteArrayList ist eine thread-safe Variante von ArrayList. Genau wie ArrayList verwaltet CopyOnWriteArray ein Array zum Speichern seiner Elemente. Der Unterschied liegt darin, dass alle mutierten Aktionen wie add, set, remove, clear,... eine neue Kopie des von ihm verwalteten Array erstellen.
public class CopyOnWriteArrayList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
Schauen Sie, was beim Hinzufügen eines Element ins CopyOnWriteArrayList passiert:
Die Kosten für die Verwendung von CopyOnWriteArrayList sind sehr hoch. Sie zahlen mehr für die Ressourcen und Leistung. CopyOnWriteArrayList ist jedoch nützlich, wenn Sie beim Durchlaufen (traversal) der Elemente der Liste keine Synchronisierung durchführen können oder möchten.
Zum besseren Verständnis stellen Sie sich eine Situtation vor, in der zwei Thread ein dasselbes Objekt List verwenden. Während der Durchlaufzeit von Thread-A (traversal) durch die Elemente von List werden die Vorgänge vom Einfügen oder Aktualisierung in List für die Datenintegrität eingefroren. Dies wirkt sich jedoch offensichtlich auf die Vorgänge von Thread-B.
Wenn Sie ein Objekt Iterator aus CopyOnWriteArrayList erstellen, können Sie die Elemente des aktuellen Arrays durchlaufen (wenn Iterator erstellt wurde). Die Elemente des Arrays ändern sich während des Vorhandenseins vom Iterator nicht. Das schafft, da alle Vorgänge zum add, set, remove, clear, usw der CopyOnWriteArrayList ein anderes Array erstellen, das eine Kopie vom aktuellen Arrays ist.
CopyOnWriteArrayListEx.java
package org.o7planning.copyonwritearraylist.ex;

import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteArrayListEx {

    public static void main(String[] args) {
        // Create a CopyOnWriteArrayList object:
        List<String> list = new CopyOnWriteArrayList<String>();
        list.add("A");
        list.add("B");
        list.add("C");
        
        Iterator<String> iterator1 = list.iterator();
        
        list.add("X1");
        list.add("X2");
        
        Iterator<String> iterator2 = list.iterator();
        
        System.out.println("--- Iterator 1: -----");
        while(iterator1.hasNext()) {
            System.out.println(iterator1.next());
        }
        
        System.out.println("--- Iterator 2: -----");
        while(iterator2.hasNext()) {
            System.out.println(iterator2.next());
        }
    }
}
Output:
--- Iterator 1: -----
A
B
C
--- Iterator 2: -----
A
B
C
X1
X2
Die Vorgänge von Elementsänderung an Iterator(add, set, remove) werden nicht unterstützt. Diese Methoden löst UnsupportedOperationException aus.
Stream
Das Durchlaufen der Elemente von CopyOnWriteArrayList durch Stream führt zu denselben Ergebnissen wie der Iterator.
CopyOnWriteArrayListEx2.java
package org.o7planning.copyonwritearraylist.ex;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Stream;

public class CopyOnWriteArrayListEx2 {

    public static void main(String[] args) {
        // Create a CopyOnWriteArrayList object:
        List<String> list = new CopyOnWriteArrayList<String>();
        list.add("A");
        list.add("B");
        list.add("C");
        
        Stream<String> stream1 = list.stream();
        
        list.add("X1");
        list.add("X2");
        
        Stream<String> stream2 = list.stream();
        
        System.out.println("--- Stream 1: -----");
        stream1.forEach(System.out::println);
        
        System.out.println("--- Stream 2: -----");
        stream2.forEach(System.out::println);
    }
}
Output:
--- Stream 1: -----
A
B
C
--- Stream 2: -----
A
B
C
X1
X2
Zusätzlich zu den obengemeinten Besonderheiten ist CopyOnWriteArrayList auch eine normale List. Sie können weitere Beispiel für List im folgenden Artikel finden: