English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Die Implementierung der Größe veränderbaren Arrays des List-Interfaces. Es implementiert alle optionalen List-Operationen und ermöglicht alle Elemente einschließlich null. Neben der Implementierung des List-Interfaces bietet diese Klasse einige Methoden, um die Größe des Arrays zu verändern, das zur Speicherung der Liste verwendet wird. (Diese Klasse ist im Grunde äquivalent zur Vector-Klasse, außer dass sie nicht synchronisiert ist.) Die Operationen size, isEmpty, get, set, iterator und listIterator laufen in festem Zeitverlauf ab. Die add-Operation läuft in verteilter festem Zeitverlauf ab, das bedeutet, dass das Hinzufügen von n Elementen O(n) Zeit erfordert. Alle anderen Operationen laufen in linearer Zeit ab (im Großen und Ganzen). Im Vergleich zu den Konstanten Faktoren der LinkedList-Implementierung sind die Konstanten Faktoren dieser Implementierung niedriger. Jede ArrayList-Instanz hat eine Kapazität. Diese Kapazität ist die Größe des Arrays, das zur Speicherung der Liste der Elemente verwendet wird. Sie ist immer mindestens so groß wie die Größe der Liste. Mit jedem Hinzufügen von Elementen wächst die Kapazität der ArrayList automatisch. Die Details der Wachstumsstrategie sind nicht spezifiziert, da dies nicht nur eine verteilte festgelegte Zeitverzögerung bei der Hinzufügung von Elementen ist. Bevor eine große Anzahl von Elementen hinzugefügt wird, kann die Anwendung die Operation ensureCapacity verwenden, um die Kapazität der ArrayList-Instanz zu erhöhen. Dies kann die Anzahl der Erweiterungen reduzieren, die bei der Erweiterung erforderlich sind.
Beachten Sie, dass diese Implementierung nicht synchronisiert ist.
Wenn mehrere Threads gleichzeitig auf eine ArrayList-Instanz zugreifen und mindestens einer der Threads die Liste strukturell ändert, muss sie extern synchronisiert werden. (Strukturelle Änderungen beziehen sich auf jede Operation, die das Hinzufügen oder Entfernen eines oder mehrerer Elemente umfasst, oder eine explizite Anpassung der Größe der Grunddatenstruktur; das Setzen des Wertes eines Elements ist keine strukturelle Änderung.) Dies wird in der Regel durch Synchronisationsoperationen auf das natürliche Objekt, das die Liste einschließt, erreicht. Wenn ein solches Objekt nicht vorhanden ist, sollte die Liste mit der Methode Collections.synchronizedList "verpackt" werden. Dies sollte am besten beim Erstellen der Liste erfolgen, um unerwünschte, nicht-synchronisierte Zugriffe zu vermeiden:
Listlist=Collections.synchronizedList(newArrayList(...));
Die von diesen iterator- und listIterator-Methode zurückgegebenen Iteratoren sind schnell abbruchend: Nach dem Erstellen des Iterators wird bei jeder Änderung der Liste, die nicht durch das remove- oder add-Methode des Iterators selbst vorgenommen wird, ConcurrentModificationException ausgelöst. Daher bricht der Iterator bei parallelen Änderungen schnell vollständig ab, anstatt das Risiko zu laufen, dass zu einem späteren, nicht festgelegten Zeitpunkt irgendein nicht bestimmtes Verhalten auftritt.
Beachten Sie, dass das schnelle Ausfallen des Iterators nicht garantiert werden kann, da in der Regel keine harte Garantie für das Auftreten oder Nichtauftreten unsynchronisierter paralleler Änderungen gegeben werden kann. Ein schneller abbruchender Iterator wird sein Bestes tun, um ConcurrentModificationException auszulösen. Daher ist es ein Fehler, ein Programm zu schreiben, das von diesem Ausnahme abhängt, um die Richtigkeit solcher Iteratoren zu verbessern: das schnelle Ausfallen des Iterators sollte nur zur Fehlerdetektion verwendet werden.
Wie oben gezeigt, wird jetzt eine Liste erstellt, eine Thread führt Schreiboperationen auf die Liste durch, und ein anderer Thread führt Löschoperationen durch
import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Random; public class MyArrayList { /** * Erstellen Sie eine Liste, eine Thread schreibt, ein anderer liest iterator und listIterator geben Iteratoren zurück, die schnell fehlschlagen */ public void readWrite() { List<Integer> nums = new ArrayList<Integer>(); List<Integer> synNums = Collections.synchronizedList(nums); //Starten Sie den Schreibthread new WriteListThread(synNums).start(); //Starten Sie den Löschthread new DeleteListThread(synNums).start(); } public static void main(String[] args) { new MyArrayList().readWrite(); } } class WriteListThread extends Thread { private List<Integer> nums; public WriteListThread(List<Integer> nums) { super(“WriteListThread”); this.nums = nums; } // Dauerhaftes Schreiben von Elementen1 public void run() { while (true) { nums.add(new Random().nextint(1000)); System.out.println(Thread.currentThread().getName()); } } } class DeleteListThread extends Thread { private List<Integer> nums; public DeleteListThread(List<Integer> nums) { super(“DeleteListThread”); this.nums = nums; } // Löschen des ersten Elements public void run() { while (true) { try{ System.out.println(Thread.currentThread().getName())+:+nums.remove(0)); } catch(Exception e){ continue ; } } } }
Durch List<Integer> synNums = Collections.synchronizedList(nums); kann auf atomare Operationen synchronisiert werden, aber warum fügen die offiziellen API-Beispiele selbst manuell Synchronisation hinzu?
List list = Collections.synchronizedList(new ArrayList()); synchronized(list) { Iterator i = list.iterator(); // Muss im gesynchromatisierten Block sein while (i.hasNext()) foo(i.next()); }
Betrachten Sie den Quellcode von Collections.synchronizedList
SynchronizedCollection(Collection<E> c) { if (c==null) throw new NullPointerException(); this.c = c; mutex = this; }
import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Random; public class MyArrayList { /** * Erstellen Sie eine Liste, eine Thread schreibt, ein anderer liest iterator und listIterator geben Iteratoren zurück, die schnell fehlschlagen */ public void readWrite() { List<Integer> nums = new ArrayList<Integer>(); List<Integer> synNums = Collections.synchronizedList(nums); //Starten Sie den Schreibthread new WriteListThread(synNums).start(); //Starten Sie den Löschthread new DeleteListThread(synNums).start(); } public static void main(String[] args) { new MyArrayList().readWrite(); } } class WriteListThread extends Thread { private List<Integer> nums; public WriteListThread(List<Integer> nums) { super("WriteListThread"); this.nums = nums; } // Dauerhaftes Schreiben von Elementen1 public void run() { while (true) { nums.add(new Random().nextint(1000)); System.out.println(Thread.currentThread().getName()); } } } class DeleteListThread extends Thread { private List<Integer> nums; public DeleteListThread(List<Integer> nums) { super("DeleteListThread"); this.nums = nums; } // Löschen des ersten Elements public void run() { while (true) { try{ System.out.println(Thread.currentThread().getName())+":"+nums.remove(0)); } catch(Exception e){ continue ; } } } }
Für die Synchronisierung der Sammlung ist es erforderlich, die Synchronisierungs-Wrapperklasse von Collections zu verwenden, und für nicht atomare Operationen müssen die Benutzer manuell synchronisieren
Wie gezeigt, fügen Sie einen Thread hinzu, um die Sammlung zu lesen
class ReadListThread extends Thread { private List<Integer> nums; public ReadListThread(List<Integer> nums) {}} super(“ReadListThread”); this.nums = nums; } // Ununterbrochenes Lesen von Elementen, nicht atomare Operationen, müssen manuell gesperrt werden public void run() { while (true) { //Ruhezeit, um den Schloss-Schlüssel an andere Threads zu übergeben try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } synchronized (nums) { if (nums.size() > 100) { Iterator<Integer> iter = nums.iterator(); while (iter.hasNext()) { System.out.println(Thread.currentThread().getName()) + : + iter.next()); ; } } else{ try { nums.wait(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } } }
Zusammenfassung
Das ist der vollständige Inhalt dieses Artikels über die Thread-Synchronisierung des Java Collection Frameworks. Ich hoffe, er hilft Ihnen weiter. Interessierte Freunde können weiterhin andere relevante Themen auf dieser Website lesen. Wenn es Mängel gibt, freuen wir uns über Ihre Kommentare. Vielen Dank für die Unterstützung der Freunde dieser Website!
Erklärung: Der Inhalt dieses Artikels wurde aus dem Internet entnommen und gehört dem Urheberrechtsinhaber. Der Inhalt wurde von Internetbenutzern freiwillig beigesteuert und hochgeladen. Diese Website besitzt keine Eigentumsrechte und hat den Inhalt nicht von Hand bearbeitet. Diese Website übernimmt keine rechtlichen Verantwortlichkeiten. Wenn Sie Inhalte finden, die möglicherweise urheberrechtlich geschützt sind, senden Sie bitte eine E-Mail an: notice#oldtoolbag.com (bei der Abgabe von E-Mails, ersetzen Sie bitte # durch @) melden Sie Missbrauch und fügen Sie relevante Beweise bei. Sobald nachgewiesen, wird diese Website den涉嫌侵权的内 容立即删除。