JavaRush /جاوا بلاگ /Random-SD /A Tale of Two Iterators: جاوا ۾ مقابلي واري تبديلي واري ح...

A Tale of Two Iterators: جاوا ۾ مقابلي واري تبديلي واري حڪمت عملي

گروپ ۾ شايع ٿيل
نوٽ جو ليکڪ گرزيگورز ميرڪ آهي، جيڪو ڪرڪو (پولينڊ) مان هڪ سافٽ ويئر ڊولپر آهي. هن تقريباً 6 سال اڳ جاوا ۾ ترقي ڪرڻ شروع ڪئي، جڏهن ته اڃا يونيورسٽيءَ ۾ هو، ۽ ان وقت کان وٺي هن علائقي ۾ پنهنجي صلاحيتن کي نهايت محنت سان پالي رهيو آهي. هو خاص طور تي JVM ڪارڪردگي ۽ اصلاح ۾ دلچسپي رکي ٿو، جيڪو هن جي بلاگ تي خاص طور تي لکي ٿو .
A Tale of Two Iterators: Competitive Modification Strategies in Java - 1
جاوا جا ڪجهه مشهور انٽرويو سوالن ۾ شامل آهن: ناڪام-تيز ۽ ناڪام-محفوظ آئٽرٽرز جي وچ ۾ ڇا فرق آهي؟ ان جو سڀ کان وڌيڪ آسان جواب آهي: هڪ ناڪام-تيز آئيٽرٽر هڪ ConcurrentModificationException اڇلائي ٿو جيڪڏهن مجموعو iteration دوران تبديل ٿئي ٿو، پر هڪ ناڪام-محفوظ آئٽرٽر نٿو ڪري. جيتوڻيڪ اهو آواز ڪافي معنيٰ وارو آهي، اهو واضح ناهي ته انٽرويو وٺندڙ جو مطلب ڇا آهي ناڪام-محفوظ؟ Java Language Specifications هن اصطلاح جي وضاحت نه ڪندا آهن اُچارن جي حوالي سان. تنهن هوندي به، چار مقابلي ۾ ترميمي حڪمت عمليون آهن.

مقابلي واري تبديلي

پهرين، اچو ته وضاحت ڪريون ته مقابلي واري (يا متوازي) ترميم ڇا آهي. اچو ته چئون ته اسان وٽ هڪ مجموعو آهي ۽ جڏهن ائٽيٽر فعال هوندو آهي، ڪجهه تبديليون اينديون آهن جيڪي هن آئٽرٽر مان نه اينديون آهن. انهي حالت ۾، اسان هڪ مقابلي واري تبديلي حاصل ڪندا آهيون. اچو ته توهان کي هڪ سادي مثال ڏيان: اچو ته چئو ته اسان وٽ ڪيترائي موضوع آهن. پھريون ڌاڳو ٻيهر ورجائي ٿو، ۽ ٻيو ٿريڊ ساڳئي مجموعي مان عناصر داخل ڪري ٿو يا ختم ڪري ٿو. تنهن هوندي، اسان حاصل ڪري سگهون ٿا ConcurrentModificationException جڏهن هڪ واحد موضوع واري ماحول ۾ هلندي:
List<String> cities = new ArrayList<>();
cities.add(Warsaw);
cities.add(Prague);
cities.add(Budapest);

Iterator<String> cityIterator = cities.iterator();
cityIterator.next();
cities.remove(1);
cityIterator.next(); // генерирует ConcurrentModificationException

تڪڙا تڪڙا

مٿي ڏنل ڪوڊ جو ٽڪرو هڪ ناڪام فاسٽ آئٽرٽر جو هڪ مثال آهي. جئين توهان ڏسي سگهو ٿا، هڪ ConcurrentModificationException اڇلايو ويو جڏهن ٻئي عنصر کي ٻيهر حاصل ڪرڻ جي ڪوشش ڪئي وئي آئيٽرٽر . هڪ ائٽريٽر ڪيئن ڄاڻي ٿو ته مجموعو تبديل ڪيو ويو آهي جڏهن کان اهو ٺاهيو ويو آهي؟ مثال طور، مجموعي ۾ تاريخ/ٽائم اسٽمپ ٿي سگھي ٿي، چئو lastModified . جڏهن هڪ آئٽرٽر ٺاهي، توهان کي هن فيلڊ کي نقل ڪرڻ گهرجي ۽ ان کي هڪ آئٽرٽر اعتراض ۾ ذخيرو ڪرڻ گهرجي. پوءِ، هر دفعي ايندڙ() طريقي کي سڏيو ويندو آهي، توهان آسانيءَ سان گڏ ڪرڻ جي آخري ترميمي قدر جو مقابلو ڪندا ائٽرٽر جي ڪاپي سان. ھڪڙو بلڪل ساڳيو طريقو استعمال ڪيو ويو آھي، مثال طور، ArrayList طبقي جي عمل ۾ . ان ۾ ھڪڙو مثال آھي متغير modCount جيڪو ذخيرو ڪري ٿو تعداد جو تعداد لسٽ کي تبديل ڪيو ويو آھي:
final void checkForComodification() {
   if (modCount != expectedModCount)
       throw new ConcurrentModificationException();
}
اهو نوٽ ڪرڻ ضروري آهي ته ناڪام-تيز آئيٽرٽر هڪ بهترين نسل جي بنياد تي هلن ٿا، مطلب ته اها ڪا به گارنٽي نه آهي ته هڪ سمورو ترميم جي صورت ۾ هڪ ConcurrentModificationException اڇلايو ويندو. تنهن ڪري توهان کي انهن تي ڀروسو نه ڪرڻ گهرجي - بلڪه، انهن کي استعمال ڪيو وڃي غلطيون ڳولڻ لاءِ. گھڻا غير سمورو مجموعا ناڪام-تيز آئيٽرٽر مهيا ڪن ٿا.

ڪمزور مطابقت

java.util.concurrent پيڪيج ۾ اڪثر سمورو مجموعو (جهڙوڪ ConcurrentHashMap ۽ سڀ کان وڌيڪ قطار ) ضعيف طور تي هڪجهڙائي وارا اکر مهيا ڪن ٿا. هن اصطلاح جي معنيٰ تمام چڱيءَ طرح بيان ڪيل دستاويز ۾ ڏنل آهي :
  • انهن کي ٻين عملن سان گڏوگڏ عمل ڪري سگهجي ٿو
  • اهي ڪڏهن به هڪ ConcurrentModificationException اڇليندا آهن
  • اهي ضمانت آهن ته موجوده عنصرن کي ٽريڪ ڪرڻ جي وقت تي جڏهن آئٽرٽر هڪ ڀيرو ٺاهيو ويو هو، ۽ ڪري سگهن ٿا (پر گهربل نه آهي) بعد ۾ تبديلين کي ظاهر ڪن ٿا.

سنيپ شاٽ

هن حڪمت عملي سان، آئٽرٽر ان جي ٺهڻ وقت گڏ ڪرڻ جي حالت سان لاڳاپيل آهي - هي مجموعو جو هڪ سنيپ شاٽ آهي. ڪنهن به تبديليءَ جي نتيجي ۾ اصل گڏ ڪرڻ جو نتيجو بنيادي ڊيٽا جي ڍانچي جي نئين ورزن جي پيدائش ۾ آهي. هي اسان جي سنيپ شاٽ کي اڻڄاتل ڇڏي ٿو، تنهنڪري اهو مجموعن ۾ تبديلين کي ظاهر نٿو ڪري جيڪا آئٽرٽر ٺهڻ کان پوء ٿي. هي سٺي پراڻي ڪاپي-آن-لکڻ (COW) ٽيڪنڪ آهي . اهو مڪمل طور تي سمورو ترميمن جي مسئلي کي حل ڪري ٿو، تنهنڪري هڪ ConcurrentModificationException هن طريقي سان پيدا نه ڪيو ويو آهي. اضافي طور تي، آئٽرٽر آپريشن کي سپورٽ نٿا ڪن جيڪي عناصر کي تبديل ڪن ٿا. ڪاپي-آن-لکڻ جا مجموعا استعمال ڪرڻ لاءِ ڏاڍا مهانگو هوندا آهن، پر اهو انهن کي استعمال ڪرڻ لاءِ سمجهه ۾ اچي ٿو جيڪڏهن تبديليون گهڻيون گهٽ ٿين ٿيون ته آئٽرٽر ٽرورسلز کان. مثال آهن CopyOnWriteArrayList ۽ CopyOnWriteArraySet ڪلاس .

اڻڄاتل رويي

توهان کي شايد غير تعريف ٿيل رويي سان منهن ڏيڻو پوي ٿو ميراثي گڏ ڪرڻ جي قسمن جهڙوڪ Vector ۽ Hashtable . ٻنهي وٽ معياري ناڪام-فاسٽ آئٽرٽر آهن، پر ان کان علاوه، اهي ڳڻپ جي انٽرفيس جي عملن جي استعمال جي اجازت ڏين ٿا ، ۽ انهن کي خبر ناهي ته سمورو ترميم جي صورت ۾ ڪيئن برتاءُ ڪجي. توهان شايد ڪجهه عنصرن کي بار بار يا غائب ٿيڻ، يا اڃا به ڪجهه عجيب استثنا سان منهن ڏئي سگهون ٿا. اهو بهتر آهي ته انهن سان راند نه ڪريو!
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION