استثناء مرضع متزامن للمكترونات
-
20-09-2019 - |
سؤال
سيقوم هذا الرمز بإلقاء استثناء التعديل المتزامن إذا تم تعديل القائمة في Dosomething (). هل من الممكن تجنب ذلك عن طريق إرفاق الرمز في بعض الكتلة المتزامنة؟
List l = Collections.synchronizedList(new ArrayList());
// normal iteration -- can throw ConcurrentModificationException
// may require external synchronization
for (Iterator i=list.iterator(); i.hasNext(); ) {
doSomething(i.next());
}
المحلول
إذا كنت تقوم بإزالة عنصر من القائمة، فيمكنك القيام بذلك عن طريق الاتصال
iterator.remove()
بدلاً منlist.remove(iterator.next())
إذا قمت بإضافة عنصر - حسنا، قم بإنشاء نسخة من القائمة المكرمة وإضافتها هناك
إذا كان مقتطف الكود أعلاه جزءا من نفس الطريقة، فلن تحتاج إلى قائمة متزامنة أو كتل متزامنة - لا يمكن لأي ترابط آخر الوصول إلى القائمة المحلية.
نصائح أخرى
أنت تستطيع تعديل أ Collection
أثناء التكرار بشأنه إذا قمت بذلك من خلال Iterator
واجهه المستخدم. يمكنك استخدام Iterator.remove()
لإزالة العناصر.
لا يمكنك تعديله أثناء التكرار بشأنه. مزامنة لن يساعد هنا.
تحرير: لقد نسيت أن يكون للماء remove
طريقة. لذلك من الممكن إزالته.
وأنا أتفق مع الآخرين حول Iterator
و remove()
.
حول المزامنة، أردت أن أضيف أن المزامنة مصممة للتحكم في التفاعلات بين المواضيع المختلفة.
من النموذجي أن يكون لك كائن عدة طرق متزامنة، وأن المرء سوف يسميه آخر. لذلك قرر مصممون اللغة أن نفس الخيط لن يتم حظره بنفسه بمزامنة.
أيضا، أفكر في الأمر، يتم حظر موضوعه في انتظار نفسه، لديك رائعة مجاعة إنطباع! ؛-)
لذلك هذا يجيب أحد أسئلتك: لا يمكن تجنب المشكلة عن طريق مزامنة التعليمات البرمجية الخاصة بك.
يستخدم CopyOnWriteArrayList
بدلا من قائمة الصفيف متزامنة
List l = Collections.synchronizedList(new ArrayList());
synchronized(l) {
// normal iteration -- can throw ConcurrentModificationException
// may require external synchronization
for (Iterator i=list.iterator(); i.hasNext(); ) {
doSomething(i.next());
}
}