logo

ConcurrentModificationException у Java

Виняток ConcurrentModificationException виникає, коли об’єкт намагаються змінити одночасно, коли це неприпустимо. Цей виняток зазвичай виникає, коли хтось працює з Класи Java Collection .

Наприклад - Неприпустимо для потоку змінювати колекцію, коли інший потік виконує її. Це тому, що результат ітерації стає невизначеним разом із ним. Деякі реалізації класу Iterator створюють цей виняток, включаючи всі ті реалізації Iterator загального призначення, які надаються JRE. Ітератори, які це роблять, називаються безвідмовний оскільки вони швидко створюють виняток, щойно стикаються з такою ситуацією, замість того, щоб стикатися з невизначеною поведінкою колекції будь-коли в майбутньому.

java hasnext

Примітка:Не обов’язково, що цей виняток буде викинуто лише тоді, коли інший потік намагатиметься змінити об’єкт колекції. Це також може статися, якщо один потік має деякі викликані методи, які намагаються порушити контракт об’єкта. Це може статися, коли потік намагається змінити об’єкт колекції, поки він повторюється деякимишвидкий ітератор, ітератор видасть виняток.

приклад

 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); } } } 

Вихід:

ConcurrentModificationException у Java

У цьому повідомленні сказано, що виняток виникає, коли викликається наступний метод, оскільки ітератор повторює список, і ми одночасно вносимо в нього зміни. Але якщо ми внесемо зміни в хеш-карту, як наведено нижче, тоді це не викличе жодного такого винятку, оскільки розмір хеш-карти не зміниться.

Наприклад-

 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); } } } } 

Вихід:

список держав
 Map Value:1 Map Value:2 Map Value:3 

Цей приклад працює цілком нормально, оскільки, поки ітератор виконує ітерацію по карті, розмір карти не змінюється. Тільки карта оновлюється в оператор if .

Конструктори ConcurrentModificationException

Існує 4 типи конструкторів ConcurrentModificationException -

  1. public ConcurrentModificationException() -
    Це створює виняток ConcurrentModificationException без параметрів.
  2. public ConcurrentModificationException(рядкове повідомлення)
    Це створює виняток ConcurrentModificationException із детальним повідомленням із зазначенням виключення.
  3. public ConcurrentModificationException(Throwableпричина)
    Це створює виняткову ситуацію ConcurrentModificationException із причиною та повідомленням (cause==null?null:cause.toString()). Причину пізніше отримує Throwable.getCause().
  4. public ConcurrentModificationException(String message, Throwable reason)
    Це створює виняткову ситуацію ConcurrentModificationException із детальним повідомленням і причиною. (cause==null?null:cause.toString()). Повідомлення пізніше отримує Throwable.getMessage(), а причину пізніше отримує Throwable.getCause().

Як уникнути ConcurrentModificationException у багатопоточному середовищі?

Щоб уникнути ConcurrentModificationException у багатопоточному середовищі, ми можемо скористатися такими способами:

підрядок java
  1. Замість того, щоб перебирати клас колекції, ми можемо перебирати масив. Таким чином ми можемо дуже добре працювати зі списками невеликого розміру, але це призведе до зниження продуктивності, якщо розмір масиву дуже великий.
  2. Іншим способом може бути блокування списку шляхом розміщення його в синхронізованому блоці. Це неефективний підхід, оскільки це втрачає єдину мету використання багатопоточності.
  3. JDK 1.5 або вище надає класи ConcurrentHashMap і CopyOnWriteArrayList. Ці класи допомагають нам уникати виняткової ситуації одночасної модифікації.

Як уникнути ConcurrentModificationException в однопоточному середовищі?

Використовуючи функцію remove() ітератора, ви можете видалити об’єкт із основного об’єкта колекції.