Suche…


Einführung

Eine gleichzeitige Auflistung ist eine [Auflistung] [1], die den gleichzeitigen Zugriff mehrerer Threads ermöglicht. Verschiedene Threads können normalerweise den Inhalt der Auflistung durchlaufen und Elemente hinzufügen oder entfernen. Die Sammlung ist dafür verantwortlich, dass die Sammlung nicht beschädigt wird. [1]: http://stackoverflow.com/documentation/java/90/collections#t=201612221936497298484

Fadensichere Sammlungen

Standardmäßig sind die verschiedenen Collection-Typen nicht threadsicher.

Es ist jedoch ziemlich einfach, eine Sammlung threadsicher zu machen.

List<String> threadSafeList = Collections.synchronizedList(new ArrayList<String>());
Set<String> threadSafeSet = Collections.synchronizedSet(new HashSet<String>());
Map<String, String> threadSafeMap = Collections.synchronizedMap(new HashMap<String, String>());

Wenn Sie eine threadsichere Sammlung erstellen, sollten Sie niemals über die ursprüngliche Sammlung, sondern nur über den fadensicheren Wrapper darauf zugreifen.

Java SE 5

Ab Java 5 gibt es in java.util.collections mehrere neue thread-sichere Sammlungen, die die verschiedenen Collections.synchronized Methoden nicht benötigen.

List<String> threadSafeList = new CopyOnWriteArrayList<String>();
Set<String> threadSafeSet = new ConcurrentHashSet<String>();
Map<String, String> threadSafeMap = new ConcurrentHashMap<String, String>();

Gleichzeitige Sammlungen

Gleichzeitige Auflistungen sind eine Verallgemeinerung von Thread-sicheren Auflistungen, die eine breitere Verwendung in einer gleichzeitigen Umgebung ermöglichen.

Während für thread-sichere Auflistungen sichere Elemente hinzugefügt oder aus mehreren Threads entfernt werden, ist für sie nicht unbedingt eine sichere Iteration im selben Kontext erforderlich (eine Collection kann möglicherweise nicht durch die Collection in einem Thread sicher durchlaufen werden, während eine andere sie durch Hinzufügen von / ändert). Elemente entfernen).

Hier werden gleichzeitige Sammlungen verwendet.

Da die Iteration häufig die addAll mehrerer Massenmethoden in Sammlungen ist, wie addAll , removeAll oder auch das Kopieren von Sammlungen (durch einen Konstruktor oder auf andere Weise), Sortieren, ... ist der Anwendungsfall für gleichzeitige Sammlungen tatsächlich ziemlich groß.

Die Java SE 5 java.util.concurrent.CopyOnWriteArrayList ist beispielsweise eine Thread-sichere und gleichzeitige Lis t-Implementierung. In ihrem Javadoc heißt es:

Die Iterator-Methode "Snapshot" verwendet eine Referenz auf den Status des Arrays an dem Punkt, an dem der Iterator erstellt wurde. Dieses Array ändert sich während der Lebensdauer des Iterators nie. Daher sind Interferenzen nicht möglich, und es wird garantiert, dass der Iterator keine ConcurrentModificationException auslöst.

Daher ist der folgende Code sicher:

public class ThreadSafeAndConcurrent {

public static final List<Integer> LIST = new CopyOnWriteArrayList<>();

public static void main(String[] args) throws InterruptedException {
    Thread modifier = new Thread(new ModifierRunnable());
    Thread iterator = new Thread(new IteratorRunnable());
    modifier.start();
    iterator.start();
    modifier.join();
    iterator.join();
}

public static final class ModifierRunnable implements Runnable {
    @Override
    public void run() {
        try {
            for (int i = 0; i < 50000; i++) {
                LIST.add(i);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

public static final class IteratorRunnable implements Runnable {
    @Override
    public void run() {
        try {
            for (int i = 0; i < 10000; i++) {
                long total = 0;
                for(Integer inList : LIST) {
                    total += inList;
                }
                System.out.println(total);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
}

Eine weitere gleichzeitige Auflistung bezüglich der Iteration ist ConcurrentLinkedQueue , die besagt:

Iteratoren sind schwach konsistent und geben Elemente zurück, die den Status der Warteschlange zu einem bestimmten Zeitpunkt bei der Erstellung des Iterators widerspiegeln. Sie lösen keine java.util.ConcurrentModificationException aus und können gleichzeitig mit anderen Vorgängen fortfahren. Elemente, die seit der Erstellung des Iterators in der Warteschlange enthalten sind, werden genau einmal zurückgegeben.

Man sollte die Javadocs überprüfen, um zu sehen, ob eine Sammlung gleichzeitig ist oder nicht. Die Attribute des Iterators, die von der iterator() -Methode zurückgegeben werden ("Fail Fast", "schwach konsistent", ...), sind das wichtigste Attribut, nach dem gesucht werden soll.

Thread-sichere, aber nicht gleichzeitige Beispiele

Ändern Sie im obigen Code die LIST Deklaration in

public static final List<Integer> LIST = Collections.synchronizedList(new ArrayList<>());

Kann (und wird statistisch gesehen auf den meisten modernen Multi-CPU / Core-Architekturen) zu Ausnahmen führen.

Synchronisierte Auflistungen aus den Collections Utility-Methoden sind threadsicher für das Hinzufügen / Entfernen von Elementen, nicht jedoch für die Iteration (es sei denn, die zugrunde liegende Auflistung ist bereits übergeben).

Einfügen in ConcurrentHashMap

public class InsertIntoConcurrentHashMap
{

    public static void main(String[] args)
    {
        ConcurrentHashMap<Integer, SomeObject> concurrentHashMap = new ConcurrentHashMap<>();

        SomeObject value = new SomeObject();
        Integer key = 1;

        SomeObject previousValue = concurrentHashMap.putIfAbsent(1, value);
        if (previousValue != null)
        {
            //Then some other value was mapped to key = 1. 'value' that was passed to
            //putIfAbsent method is NOT inserted, hence, any other thread which calls
            //concurrentHashMap.get(1) would NOT receive a reference to the 'value'  
            //that your thread attempted to insert. Decide how you wish to handle             
            //this situation.
        }

       else
       {
            //'value' reference is mapped to key = 1.
       }
    }
}


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow