একটি সংশোধন Collectionযখন iterating মাধ্যমে Collectionব্যবহার করে একটি Iteratorহয় অনুমতি নেই অধিকাংশ দ্বারা Collectionক্লাস। জাভা লাইব্রেরি Collectionএটির সাথে "একযোগে পরিবর্তন" পুনরুক্তি করার সময় কিছু সংশোধন করার প্রচেষ্টা বলে। দুর্ভাগ্যক্রমে একমাত্র সম্ভাব্য কারণটি একাধিক থ্রেড দ্বারা একযোগে সংশোধন করার পরামর্শ দেয়, তবে এটি তেমন নয়। শুধুমাত্র একটি থ্রেড ব্যবহার করে Collection(ব্যবহার করে Collection.iterator()বা বর্ধিত forলুপের জন্য ) একটি পুনরুক্তি তৈরি করা , পুনরাবৃত্তি শুরু করা (ব্যবহার করা Iterator.next()বা সমতুল্য বর্ধিত forলুপের শরীরে প্রবেশ করা ), সংশোধন করুন Collection, তারপরে পুনরাবৃত্তি চালিয়ে যাওয়া সম্ভব।
প্রোগ্রামারদের সহায়তা করতে , এই শ্রেণীর কিছু বাস্তবায়ন ভুল যুগ্ম পরিবর্তনটি সনাক্ত করার চেষ্টা করে এবং যদি এটি সনাক্ত করে তবে একটি নিক্ষেপ করে। যাইহোক, সমস্ত সমবর্তী পরিবর্তনগুলির সনাক্তকরণের গ্যারান্টি দেওয়া সাধারণভাবে সম্ভব এবং ব্যবহারিক নয়। সুতরাং এর ভ্রান্ত ব্যবহার সর্বদা নিক্ষেপ হয় না ।CollectionConcurrentModificationExceptionCollectionConcurrentModificationException
এর ডকুমেন্টেশন ConcurrentModificationExceptionবলেছেন:
এই ব্যতিক্রমটি এমন পদ্ধতিগুলির দ্বারা ছুঁড়ে দেওয়া যেতে পারে যেগুলি যখন এই জাতীয় পরিবর্তন অনুমোদিত না হয় তখন কোনও সামগ্রীর একযোগে সংশোধন করে ...
নোট করুন যে এই ব্যতিক্রমটি সর্বদা ইঙ্গিত দেয় না যে কোনও বস্তু একই সময়ে ভিন্ন থ্রেড দ্বারা সংশোধন করা হয়েছে। যদি কোনও এক থ্রেড কোনও পদ্ধতির অনুরোধগুলির ক্রম জারি করে যা কোনও বস্তুর চুক্তি লঙ্ঘন করে তবে অবজেক্টটি এই ব্যতিক্রমটিকে ছুঁড়ে ফেলতে পারে ...
নোট করুন যে ব্যর্থ-দ্রুত আচরণের গ্যারান্টি দেওয়া যায় না, যেমনটি সাধারণভাবে বলা যায়, অযৌক্তিক সমান্তরাল পরিবর্তনের উপস্থিতিতে কোনও কঠোর গ্যারান্টি দেওয়া অসম্ভব। ব্যর্থ-দ্রুত ক্রিয়াকলাপগুলি ConcurrentModificationExceptionসেরা-প্রচেষ্টা ভিত্তিতে ফেলে দেয়।
মনে রাখবেন যে
ডকুমেন্টেশন HashSet, HashMap, TreeSetএবং ArrayListক্লাস এই বলে:
পুনরুদ্ধারকারীরা [প্রত্যক্ষ বা অপ্রত্যক্ষভাবে এই শ্রেণি থেকে] ব্যর্থ দ্রুত: পুনরুক্তিটি তৈরির পরে [সংগ্রহ] যদি যে কোনও সময়ে সংশোধন করা হয় তবে পুনরাবৃত্তির নিজস্ব অপসারণ পদ্ধতি বাদ দিয়ে কোনওভাবেই Iteratorছুড়ে ফেলা হয় ConcurrentModificationException। সুতরাং, একযোগে পরিবর্তনের মুখে, পুনরুক্তিকারী ভবিষ্যতে একটি নির্ধারিত সময়ে স্বেচ্ছাসেবক, অ-সংজ্ঞাবহ আচরণের ঝুঁকির চেয়ে দ্রুত এবং পরিষ্কার ব্যর্থ হয়।
নোট করুন যে কোনও পুনরাবৃত্তকারীটির ব্যর্থ-দ্রুত আচরণের গ্যারান্টি দেওয়া যায় না যেমন এটি সাধারণভাবে বলা যায়, অযত্মাত্ত্বিক সমবর্তী পরিবর্তনের উপস্থিতিতে কোনও কঠোর গ্যারান্টি দেওয়া অসম্ভব। ব্যর্থ-দ্রুত পুনরাবৃত্তি ConcurrentModificationExceptionএকটি সেরা প্রচেষ্টা ভিত্তিতে নিক্ষেপ । অতএব, কোনও প্রোগ্রাম লিখতে ভুল হবে যা এর যথাযথতার জন্য এই ব্যতিক্রমটির উপর নির্ভর করে: পুনরাবৃত্তিকারীদের ব্যর্থ-দ্রুত আচরণ কেবল বাগগুলি সনাক্ত করতে ব্যবহার করা উচিত ।
আবার নোট করুন যে আচরণটির "গ্যারান্টি দেওয়া যায় না" এবং কেবল "সেরা-প্রচেষ্টা ভিত্তিতে"।
Mapইন্টারফেসের বিভিন্ন পদ্ধতির ডকুমেন্টেশন এটিকে বলে:
অবিচ্ছিন্ন বাস্তবায়নগুলি এই পদ্ধতিটিকে ওভাররাইড করা উচিত এবং সর্বোত্তম চেষ্টাের ভিত্তিতে ConcurrentModificationExceptionযদি এটি সনাক্ত হয় যে ম্যাপিং ফাংশনটি গণনার সময় এই মানচিত্রটি পরিবর্তন করে। একযোগে বাস্তবায়নগুলি এই পদ্ধতিটিকে ওভাররাইড করে এবং সর্বোত্তম প্রচেষ্টার ভিত্তিতে, IllegalStateExceptionযদি এটি সনাক্ত হয় যে ম্যাপিং ফাংশনটি গণনার সময় এই মানচিত্রটি পরিবর্তন করে এবং ফলস্বরূপ গণনা কখনই সম্পূর্ণ হয় না।
আবার মনে রাখবেন যে সনাক্তকরণের জন্য কেবলমাত্র "সেরা-প্রচেষ্টা ভিত্তি" প্রয়োজন, এবং ConcurrentModificationExceptionএগুলি কেবলমাত্র অবিকৃত (নন থ্রেড-নিরাপদ) শ্রেণীর জন্য সুস্পষ্টভাবে প্রস্তাবিত।
ডিবাগ ConcurrentModificationException
সুতরাং, যখন আপনি কোনও কারণে স্ট্যাক-ট্রেস দেখেন ConcurrentModificationException, আপনি তাত্ক্ষণিকভাবে ধরে নিতে পারবেন না যে কারণটি একটিতে অরক্ষিত বহু-থ্রেড অ্যাক্সেস Collection। কোন শ্রেণীর ব্যতিক্রম ছুঁড়েছে তা নির্ধারণ করতে আপনাকে অবশ্যই স্ট্যাক-ট্রেস পরীক্ষা করতে হবে Collection(শ্রেণীর কোনও পদ্ধতি প্রত্যক্ষ বা অপ্রত্যক্ষভাবে এটিকে নিক্ষেপ করবে) এবং কোন Collectionবস্তুর জন্য। তারপরে আপনাকে অবশ্যই পরীক্ষা করতে হবে যেখান থেকে সেই বস্তুটি সংশোধন করা যেতে পারে।
- সর্বাধিক সাধারণ কারণটি হল
Collectionএকটি বর্ধিত forলুপের মধ্যে পরিবর্তনটি Collection। আপনি কেবল Iteratorআপনার উত্স কোডে কোনও অবজেক্ট দেখতে পাচ্ছেন না তার অর্থ এই নয় যে সেখানে কোনও Iteratorনেই! ভাগ্যক্রমে, ত্রুটিযুক্ত forলুপের একটি বিবৃতি সাধারণত স্ট্যাক-ট্রেসে থাকবে, সুতরাং ত্রুটিটি সনাক্ত করা সাধারণত সহজ is
- একটি ট্রিকায়ার কেস তখন হয় যখন আপনার কোডটি
Collectionঅবজেক্টের রেফারেন্সের চারপাশে পাস করে । দ্রষ্টব্য যে সংগ্রহগুলির অবিশ্বাস্য দৃশ্য (যেমন উত্পাদিত Collections.unmodifiableList()) সংশোধনযোগ্য সংগ্রহের একটি রেফারেন্স ধরে রাখে, সুতরাং "অপরিবর্তনীয়" সংগ্রহের উপর পুনরাবৃত্তি ব্যতিক্রমটিকে ছুঁড়ে ফেলতে পারে (পরিবর্তন অন্যত্র করা হয়েছে)। অন্যান্য মতামত আপনার এর Collectionযেমন সাব তালিকা , Mapপ্রবেশ সেট এবং Mapকী সংকলন এছাড়াও মূল (সংশোধনযোগ্য) এর রেফারেন্স ধরে রাখা Collection। এমনকি একটি থ্রেড-নিরাপদ জন্য একটি সমস্যা হতে পারে Collection, যেমন CopyOnWriteList; অনুমান করবেন না যে থ্রেড-নিরাপদ (সমবর্তী) সংগ্রহগুলি কখনই ব্যতিক্রম ছুঁড়ে ফেলতে পারে না।
- কোন ক্রিয়াকলাপ কোনওটিকে সংশোধন
Collectionকরতে পারে কিছু ক্ষেত্রে অপ্রত্যাশিত হতে পারে। উদাহরণস্বরূপ, LinkedHashMap.get()এর সংগ্রহটি পরিবর্তন করে ।
- কঠিন মামলা যখন ব্যতিক্রম হয় একাধিক থ্রেড দ্বারা সমবর্তী পরিমার্জন কারণে।
একযোগে পরিবর্তন ত্রুটি রোধ করতে প্রোগ্রামিং
সম্ভব হলে, কোনও সামগ্রীতে সমস্ত উল্লেখ সীমাবদ্ধ করুন Collection, সুতরাং সমবর্তী পরিবর্তনগুলি রোধ করা সহজ। করুন Collectionএকটি privateবস্তু বা একটি স্থানীয় পরিবর্তনশীল, এবং রেফারেন্স ফেরত না Collectionপদ্ধতি থেকে বা তার iterators। তখনই অনেক পরীক্ষা করার সহজ সব জায়গায় যেখানে Collectionপরিবর্তন করা যায়। যদি Collectionএকাধিক থ্রেড ব্যবহার করতে হয়, তবে থ্রেডগুলি Collectionকেবলমাত্র উপযুক্ত সিঙ্কনেজেশন এবং লকিংয়ের মাধ্যমেই অ্যাক্সেস করতে পারে তা নিশ্চিত করা কার্যকর ।