Sollte ich alte synchronisierte Vector-Auflistung, ArrayList mit synchronisierten Zugriff oder Collections.synchronizedList oder eine andere Lösung für gleichzeitigen Zugriff verwenden?
Ich sehe meine Frage weder in den verwandten Fragen noch in meiner Suche ( Machen Sie Ihre Sammlungen thread-sicher? ist nicht dasselbe).
Kürzlich musste ich eine Art von Unit-Tests für die GUI-Teile unserer Anwendung durchführen (im Wesentlichen unter Verwendung der API zum Erstellen von Rahmen, Hinzufügen von Objekten usw.). Da diese Operationen viel schneller als von einem Benutzer aufgerufen werden, zeigte es eine Reihe von Problemen mit Methoden, die versuchen, auf noch nicht erstellte oder bereits gelöschte Ressourcen zuzugreifen.
Ein besonderes Problem, das im EDT auftrat, ergab sich aus dem Durchlaufen einer verknüpften Liste von Ansichten, während sie in einem anderen Thread geändert wurde (was neben anderen Problemen zu einer ConcurrentModificationException führte). Fragen Sie mich nicht, warum es eine verknüpfte Liste anstelle einer einfachen Array-Liste war (noch weniger als wir in der Regel 0 oder 1 Ansicht innerhalb haben...), so nahm ich die häufigere ArrayList in meiner Frage (wie es einen älteren Cousin hat).
Wie auch immer, nicht super vertraut mit Gleichzeitigkeit Fragen, sah ich ein bisschen Info, und fragte sich, was zwischen dem alten (und wahrscheinlich veraltet) Vector (die synchronisierte Operationen durch Design hat), ArrayList mit einem synchronized (myList) { }
um kritische Abschnitte herum (Hinzufügen/Entfernen/Gehen-Operationen) oder unter Verwendung einer Liste, die von Collections.synchronizedList zurückgegeben wird (ich bin nicht einmal sicher, wie man Letzteres verwendet).
Ich entschied mich schließlich für die zweite Option, da ein weiterer Designfehler darin bestand, das Objekt (getViewList()-Methode...) offenzulegen, anstatt Mechanismen zu seiner Verwendung bereitzustellen.
Aber was sind die Vor- und Nachteile der anderen Ansätze?
[EDIT] Viele gute Ratschläge hier, schwer, einen auszuwählen. Ich werde mich für den ausführlicheren entscheiden, der Links und Denkanstöße enthält... :-) Der von Darron gefällt mir auch.
Zusammengefasst:
- Wie ich vermutet habe, ist Vector (und sein böser Zwilling, Hashtable wahrscheinlich auch) weitgehend veraltet, ich habe Leute gesehen, die sagen, dass sein altes Design nicht so gut ist wie die neueren Sammlungen, abgesehen von der Langsamkeit der Synchronisation, die sogar in einer Single-Thread-Umgebung erzwungen wird. Wenn wir es behalten, ist es vor allem, weil ältere Bibliotheken (und Teile der Java-API) es noch verwenden.
- Im Gegensatz zu dem, was ich dachte, Collections.synchronizedXxxx sind nicht moderner als Vector (sie scheinen zeitgenössisch zu Collections, dh. Java 1.2!) und nicht besser, eigentlich. Gut zu wissen. Kurz gesagt, ich sollte sie auch vermeiden.
- Die manuelle Synchronisierung scheint also doch eine gute Lösung zu sein. Es könnte Leistungsprobleme geben, aber in meinem Fall ist es nicht kritisch: Operationen auf Benutzeraktionen, kleine Sammlung, keine häufige Verwendung.
- java.util.concurrent-Paket, insbesondere die CopyOnWrite-Methoden, sollten Sie im Auge behalten.
Ich hoffe, ich habe es richtig gemacht... :-)