logo

ConcurrentModificationException في جافا

يحدث ConcurrentModificationException عندما تتم محاولة تعديل كائن بشكل متزامن عندما يكون ذلك غير مسموح به. يأتي هذا الاستثناء عادةً عندما يعمل الشخص فئات مجموعة جافا .

على سبيل المثال - لا يجوز لموضوع ما أن يعدل مجموعة عندما يتكرر موضوع آخر فوقها. وذلك لأن نتيجة التكرار تصبح غير محددة معه. بعض تطبيقات فئة Iterator تطرح هذا الاستثناء، بما في ذلك جميع تطبيقات Iterator ذات الأغراض العامة والتي يوفرها JRE. تسمى التكرارات التي تقوم بذلك اخفاق سريع حيث إنهم يقومون بالاستثناء بسرعة بمجرد مواجهة مثل هذا الموقف بدلاً من مواجهة سلوك غير محدد للمجموعة في أي وقت في المستقبل.

جافا سكريبت المنسدلة

ملحوظة:ليس من الضروري أن يتم طرح هذا الاستثناء فقط عندما يحاول مؤشر ترابط آخر تعديل كائن المجموعة. يمكن أن يحدث هذا أيضًا إذا كان هناك مؤشر ترابط واحد يحتوي على بعض الأساليب التي تحاول انتهاك عقد الكائن. قد يحدث هذا عندما يحاول مؤشر ترابط تعديل كائن المجموعة أثناء تكراره بواسطة البعضمكرر سريع الفشل، سوف يرمي المكرر الاستثناء.

مثال

 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 في جافا

تشير هذه الرسالة إلى أنه يتم طرح الاستثناء عند استدعاء الطريقة التالية حيث يقوم المكرر بتكرار القائمة ونقوم بإجراء تعديلات عليها في وقت واحد. ولكن إذا أجرينا تعديلات في الهاشماب كما هو موضح أدناه، فلن يؤدي ذلك إلى أي استثناء لأن حجم الهاشماب لن يتغير.

على سبيل المثال-

كم عدد المدن في الولايات المتحدة
 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 

يعمل هذا المثال بشكل جيد تمامًا، لأنه أثناء تكرار المكرر على الخريطة، لا يتغير حجم الخريطة. يتم تحديث الخريطة فقط في إذا بيان .

ذاكرة التخزين المؤقت النظيفة npm

منشئو ConcurrentModificationException

هناك 4 أنواع من منشئي ConcurrentModificationException -

  1. عام ConcurrentModificationException () -
    يؤدي هذا إلى إنشاء ConcurrentModificationException بدون أي معلمات.
  2. ConcurrentModificationException العام (رسالة سلسلة)
    يؤدي هذا إلى إنشاء ConcurrentModificationException مع رسالة مفصلة تحدد الاستثناء.
  3. استثناء ConcurrentModificationException العام (سبب قابل للرمي)
    يؤدي هذا إلى إنشاء ConcurrentModificationException مع سبب ورسالة وهي (cause==null?null:cause.toString()). يتم استرداد السبب لاحقًا بواسطة Throwable.getCause().
  4. ConcurrentModificationException العام (رسالة سلسلة، سبب يمكن طرحه)
    يؤدي هذا إلى إنشاء ConcurrentModificationException مع رسالة مفصلة وسبب. (cause==null?null:cause.toString()). يتم استرداد الرسالة لاحقًا بواسطة Throwable.getMessage() ويتم استرداد السبب لاحقًا بواسطة Throwable.getCause().

كيفية تجنب ConcurrentModificationException في بيئة متعددة الخيوط؟

لتجنب ConcurrentModificationException في بيئة متعددة الخيوط، يمكننا اتباع الطرق التالية-

  1. بدلًا من التكرار على فئة المجموعة، يمكننا التكرار على المصفوفة. بهذه الطريقة، يمكننا العمل جيدًا مع قوائم صغيرة الحجم، لكن هذا سيؤدي إلى استنفاد الأداء إذا كان حجم المصفوفة كبيرًا جدًا.
  2. هناك طريقة أخرى وهي قفل القائمة عن طريق وضعها في الكتلة المتزامنة. هذا ليس نهجا فعالا حيث أن الغرض الوحيد من استخدام مؤشرات الترابط المتعددة قد تم التخلي عنه.
  3. يوفر JDK 1.5 أو أعلى فئات ConcurrentHashMap وCopyOnWriteArrayList. تساعدنا هذه الفئات في تجنب استثناء التعديل المتزامن.

كيفية تجنب ConcurrentModificationException في بيئة ذات ترابط واحد؟

باستخدام وظيفة الإزالة () الخاصة بالمكرر، يمكنك إزالة كائن من كائن المجموعة الأساسي.