Penulis nota itu ialah Grzegorz Mirek, pembangun perisian dari Krakow (Poland). Dia mula membangun di Jawa kira-kira 6 tahun lalu, ketika masih di universiti, dan sejak itu dia tidak jemu menggilap kemahirannya dalam bidang ini. Beliau amat berminat dengan prestasi dan pengoptimuman JVM, yang merupakan perkara yang sering beliau tulis di blognya .
Beberapa soalan temu bual Java yang paling popular termasuk: Apakah perbezaan antara iterator gagal-cepat dan selamat gagal? Jawapan yang paling mudah untuk ini ialah: Peulang yang gagal-cepat membuang ConcurrentModificationException jika koleksi berubah semasa lelaran, tetapi lelaran yang gagal-selamat tidak. Walaupun ini kedengaran agak bermakna, masih tidak jelas apa yang dimaksudkan oleh penemuduga sebagai fail-safe? Spesifikasi Bahasa Java tidak mentakrifkan istilah ini berkaitan dengan iterator. Walau bagaimanapun, terdapat empat strategi pengubahsuaian kompetitif.
Pengubahsuaian kompetitif
Mula-mula, mari kita tentukan apa itu pengubahsuaian kompetitif (atau selari). Katakan kita mempunyai koleksi dan apabila iterator aktif, beberapa perubahan berlaku yang tidak datang dari iterator ini. Dalam kes ini, kami mendapat pengubahsuaian kompetitif. Biar saya berikan anda contoh mudah: katakan kita mempunyai beberapa utas. Benang pertama berulang, dan benang kedua memasukkan atau mengalih keluar elemen daripada koleksi yang sama. Walau bagaimanapun, kita boleh mendapatkan ConcurrentModificationException apabila berjalan dalam persekitaran satu benang: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
Fail-fast
Serpihan kod di atas ialah contoh lelaran yang gagal-cepat . Seperti yang anda lihat, ConcurrentModificationException telah dilemparkan apabila cuba mendapatkan semula elemen kedua daripada iterator . Bagaimanakah iterator mengetahui bahawa koleksi telah diubah suai sejak ia dicipta? Sebagai contoh, koleksi mungkin mempunyai cap tarikh/masa, katakan lastModified . Apabila membuat iterator, anda harus menyalin medan ini dan menyimpannya dalam objek iterator. Kemudian, setiap kali anda memanggil kaedah next() , anda hanya akan membandingkan nilai lastModified daripada koleksi dengan salinan daripada iterator. Pendekatan yang hampir sama digunakan, sebagai contoh, dalam pelaksanaan kelas ArrayList . Ia mempunyai modCount pembolehubah contoh yang menyimpan bilangan kali senarai telah diubah suai:final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
Adalah penting untuk ambil perhatian bahawa iterator yang gagal-cepat beroperasi pada asas baka terbaik, bermakna tiada jaminan bahawa ConcurrentModificationException akan dilemparkan sekiranya pengubahsuaian serentak. Oleh itu, anda tidak sepatutnya bergantung pada mereka - sebaliknya, ia harus digunakan untuk mengesan ralat. Kebanyakan koleksi bukan serentak menyediakan iterator yang gagal .
Konsistensi Lemah
Kebanyakan koleksi serentak dalam pakej java.util.concurrent (seperti ConcurrentHashMap dan kebanyakan Queue ) menyediakan iterator yang konsisten lemah. Maksud istilah ini dijelaskan dengan baik dalam dokumentasi :- Mereka boleh diproses serentak dengan operasi lain
- Mereka tidak pernah membuang ConcurrentModificationException
- Mereka dijamin melintasi elemen sedia ada pada masa iterator dibuat tepat sekali, dan boleh (tetapi tidak diperlukan untuk) mencerminkan pengubahsuaian berikutnya.
GO TO FULL VERSION