Výnimka ConcurrentModificationException nastane, keď sa objekt pokúsite upraviť súbežne, keď to nie je prípustné. Táto výnimka zvyčajne prichádza, keď človek pracuje s Triedy Java Collection .
Napríklad - Nie je dovolené, aby vlákno upravovalo kolekciu, keď cez ňu iteruje iné vlákno. Je to preto, že výsledok iterácie sa tým stáva nedefinovaným. Niektoré implementácie triedy Iterator vyvolávajú túto výnimku, vrátane všetkých tých všeobecných implementácií Iteratora, ktoré poskytuje JRE. Iterátory, ktoré to robia, sa nazývajú zlyhanie-rýchle pretože výnimku vyhodia rýchlo hneď, ako sa ocitnú v takejto situácii, namiesto toho, aby kedykoľvek v budúcnosti čelili neurčitému správaniu zbierky.
primárny kľúč a zložený kľúč v sql
Poznámka:Nie je povinné, že táto výnimka bude vyvolaná iba vtedy, keď sa nejaké iné vlákno pokúsi upraviť objekt Collection. Môže sa to stať aj vtedy, ak má jedno vlákno nejaké metódy, ktoré sa pokúšajú porušiť zmluvu objektu. To sa môže stať, keď sa vlákno pokúša upraviť objekt Collection, zatiaľ čo ho niektorí iterujúneúspešný iterátor, iterátor vyvolá výnimku.
Príklad
import java.awt.List; import java.util.*; public class Concurrentmodificationexception { public static void main(String[] args) { ArrayList list = new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); Iterator it = list.iterator(); while (it.hasNext()) { Integer value = it.next(); System.out.println('List Value:' + value); if (value.equals(3)) list.remove(value); } } }
Výkon:
Táto správa hovorí, že výnimka sa vyvolá, keď sa zavolá ďalšia metóda, pretože iterátor iteruje zoznam a súčasne v ňom robíme úpravy. Ale ak urobíme úpravy v hashmap, ako je uvedené nižšie, potom to nevyvolá žiadnu takú výnimku, pretože veľkosť hashmap sa nezmení.
synchronizácia vlákien
Napríklad-
import java.awt.List; import java.util.*; public class concurrentmodificationexception { public static void main(String[] args) { HashMap map = new HashMap(); map.put(1, 1); map.put(2, 2); map.put(3,3); Iterator it = map.keySet().iterator(); while(it.hasNext()) { Integer key = it.next(); System.out.println('Map Value:' + map.get(key)); if (key.equals(2)) { map.put(1, 4); } } } }
Výkon:
Map Value:1 Map Value:2 Map Value:3
Tento príklad funguje úplne dobre, pretože počas iterácie iterátora cez mapu sa veľkosť mapy nemení. Aktualizuje sa iba mapa ak vyhlásenie .
Konštruktory ConcurrentModificationException
Existujú 4 typy konštruktorov ConcurrentModificationException -
súbor c++
- public ConcurrentModificationException() -
Tým sa vytvorí ConcurrentModificationException bez parametrov. - public ConcurrentModificationException (Stringová správa)
Tým sa vytvorí výnimka ConcurrentModificationException s podrobnou správou špecifikujúcou výnimku. - public ConcurrentModificationException (možná príčina)
Toto vytvorí ConcurrentModificationException s príčinou a správou, ktorá je (cause==null?null:cause.toString()). Príčinu neskôr vyhľadá Throwable.getCause(). - public ConcurrentModificationException (reťazcová správa, príčina na vhadzovanie)
Tým sa vytvorí výnimka ConcurrentModificationException s podrobnou správou a príčinou. (cause==null?null:cause.toString()). Správa je neskôr získaná pomocou Throwable.getMessage() a príčina je neskôr získaná pomocou Throwable.getCause().
Ako sa vyhnúť ConcurrentModificationException vo viacvláknovom prostredí?
Aby sme sa vyhli výnimke ConcurrentModificationException vo viacvláknovom prostredí, môžeme postupovať podľa nasledujúcich spôsobov:
- Namiesto iterovania cez triedu kolekcie môžeme iterovať cez pole. Týmto spôsobom môžeme veľmi dobre pracovať s malými zoznamami, ale to zníži výkon, ak je veľkosť poľa veľmi veľká.
- Ďalším spôsobom môže byť uzamknutie zoznamu umiestnením do synchronizovaného bloku. Toto nie je efektívny prístup, pretože sa tým upúšťa od jediného účelu použitia viacvláknového spracovania.
- JDK 1.5 alebo vyšší poskytuje triedy ConcurrentHashMap a CopyOnWriteArrayList. Tieto triedy nám pomáhajú vyhnúť sa výnimkám zo súbežných úprav.
Ako sa vyhnúť výnimke ConcurrentModificationException v prostredí s jedným vláknom?
Pomocou funkcie remove() iterátora môžete odstrániť objekt zo základného objektu kolekcie.