Výjimka ConcurrentModificationException nastane, když se objekt pokouší upravit souběžně, když to není přípustné. Tato výjimka obvykle přichází, když se s ním pracuje Třídy Java Collection .
Například - Není přípustné, aby vlákno upravovalo kolekci, když nad ní iteruje jiné vlákno. Je to proto, že výsledek iterace se tím stává nedefinovaným. Některá implementace třídy Iterator vyvolá tuto výjimku, včetně všech těch univerzálních implementací Iteratoru, které poskytuje JRE. Iterátory, které to dělají, se nazývají selhání rychle protože výjimku vyhodí rychle, jakmile se s takovou situací setkají, než aby kdykoli v budoucnu čelili neurčitému chování kolekce.
návrh databáze v dbms
Poznámka:Není povinné, aby tato výjimka byla vyvolána pouze tehdy, když se nějaké jiné vlákno pokusí upravit objekt Collection. Může se to také stát, pokud má jedno vlákno nějaké metody, které se pokoušejí porušit smlouvu objektu. To se může stát, když se vlákno pokouší upravit objekt Collection, zatímco je některými iterovánFail-fast iterátor, iterátor vyvolá výjimku.
Pří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ýstup:
Tato zpráva říká, že výjimka je vyvolána, když je zavolána další metoda, protože iterátor iteruje seznam a současně v něm provádíme úpravy. Ale pokud provedeme úpravy v hashmap, jak je uvedeno níže, pak to nevyvolá žádnou takovou výjimku, protože velikost hashmap se nezmění.
Například-
výhody instagramu pro osobní použití
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ýstup:
Map Value:1 Map Value:2 Map Value:3
Tento příklad funguje úplně dobře, protože zatímco iterátor iteruje přes mapu, velikost mapy se nemění. Aktualizuje se pouze mapa if prohlášení .
Konstruktory ConcurrentModificationException
Existují 4 typy konstruktorů ConcurrentModificationException -
linuxové zkratky
- public ConcurrentModificationException() -
Tím se vytvoří ConcurrentModificationException bez parametrů. - public ConcurrentModificationException (Stringová zpráva)
Tím se vytvoří ConcurrentModificationException s podrobnou zprávou specifikující výjimku. - public ConcurrentModificationException (příčina k vyvolání)
Tím se vytvoří výjimka ConcurrentModificationException s příčinou a zprávou, která je (cause==null?null:cause.toString()). Příčina je později získána pomocí Throwable.getCause(). - public ConcurrentModificationException (řetězcová zpráva, příčina vhazování)
Tím se vytvoří výjimka ConcurrentModificationException s podrobnou zprávou a příčinou. (cause==null?null:cause.toString()). Zpráva je později načtena pomocí Throwable.getMessage() a příčina je později získána pomocí Throwable.getCause().
Jak se vyhnout ConcurrentModificationException ve vícevláknovém prostředí?
Abychom se vyhnuli výjimce ConcurrentModificationException ve vícevláknovém prostředí, můžeme se řídit následujícími způsoby-
- Místo iterování třídy kolekce můžeme iterovat pole. Tímto způsobem můžeme velmi dobře pracovat s malými seznamy, ale to sníží výkon, pokud je velikost pole velmi velká.
- Dalším způsobem může být uzamčení seznamu umístěním do synchronizovaného bloku. Toto není efektivní přístup, protože tím odpadá jediný účel použití vícevláknového zpracování.
- JDK 1.5 nebo vyšší poskytuje třídy ConcurrentHashMap a CopyOnWriteArrayList. Tyto třídy nám pomáhají vyhnout se výjimkám souběžných modifikací.
Jak se vyhnout ConcurrentModificationException v prostředí s jedním vláknem?
Pomocí funkce remove() iterátoru můžete odebrat objekt ze základního objektu kolekce.