Panduan untuk CopyOnWriteArrayList

1. Ikhtisar

Dalam artikel singkat ini, kita akan melihat CopyOnWriteArrayList dari paket java.util.concurrent .

Ini adalah konstruksi yang sangat berguna dalam program multi-threaded - ketika kita ingin mengulang daftar dengan cara yang aman untuk thread tanpa sinkronisasi eksplisit.

2. API CopyOnWriteArrayList

Desain CopyOnWriteArrayList menggunakan teknik yang menarik untuk membuatnya aman untuk thread tanpa perlu sinkronisasi. Ketika kita menggunakan salah satu metode modifikasi - seperti add () atau remove () - seluruh konten CopyOnWriteArrayList disalin ke dalam salinan internal baru.

Karena fakta sederhana ini, kami dapat mengulang daftar dengan cara yang aman, bahkan saat modifikasi bersamaan sedang terjadi .

Saat kita memanggil metode iterator () pada CopyOnWriteArrayList, kita mendapatkan kembali Iterator yang didukung oleh snapshot yang tidak dapat diubah dari konten CopyOnWriteArrayList .

Isinya adalah salinan persis dari data yang ada di dalam ArrayList sejak Iterator dibuat. Meskipun sementara itu beberapa utas lain menambahkan atau menghapus elemen dari daftar, modifikasi itu membuat salinan baru dari data yang akan digunakan dalam pencarian data lebih lanjut dari daftar itu.

Karakteristik struktur data ini membuatnya sangat berguna dalam kasus ketika kita mengulanginya lebih sering daripada kita memodifikasinya. Jika menambahkan elemen adalah operasi umum dalam skenario kami, maka CopyOnWriteArrayList bukanlah pilihan yang baik - karena salinan tambahan pasti akan menghasilkan kinerja sub-par.

3. Iterasi CopyOnWriteArrayList Saat Memasukkan

Katakanlah kita membuat sebuah instance dari CopyOnWriteArrayList yang menyimpan integer:

CopyOnWriteArrayList numbers = new CopyOnWriteArrayList(new Integer[]{1, 3, 5, 8});

Selanjutnya, kami ingin mengulangi array itu, jadi kami membuat instance Iterator :

Iterator iterator = numbers.iterator();

Setelah Iterator dibuat, kami menambahkan elemen baru ke daftar angka :

numbers.add(10);

Perlu diingat bahwa, saat kita membuat iterator untuk CopyOnWriteArrayList, kita mendapatkan snapshot data yang tidak dapat diubah dalam daftar pada saat iterator () dipanggil.

Karena itu, saat mengulanginya, kita tidak akan melihat angka 10 dalam iterasi:

List result = new LinkedList(); iterator.forEachRemaining(result::add); assertThat(result).containsOnly(1, 3, 5, 8);

Iterator selanjutnya menggunakan Iterator yang baru dibuat juga akan mengembalikan angka 10 yang telah ditambahkan:

Iterator iterator2 = numbers.iterator(); List result2 = new LinkedList(); iterator2.forEachRemaining(result2::add); assertThat(result2).containsOnly(1, 3, 5, 8, 10);

4. Menghapus Saat Iterasi Tidak Diizinkan

The CopyOnWriteArrayList diciptakan untuk memungkinkan kemungkinan iterasi yang aman atas elemen bahkan ketika daftar mendasari akan diubah.

Karena mekanisme penyalinan, operasi remove () di Iterator yang dikembalikan tidak diizinkan - mengakibatkan UnsupportedOperationException:

@Test(expected = UnsupportedOperationException.class) public void whenIterateOverItAndTryToRemoveElement_thenShouldThrowException() { CopyOnWriteArrayList numbers = new CopyOnWriteArrayList(new Integer[]{1, 3, 5, 8}); Iterator iterator = numbers.iterator(); while (iterator.hasNext()) { iterator.remove(); } }

5. Kesimpulan

Dalam tutorial singkat ini, kami melihat implementasi CopyOnWriteArrayList dari paket java.util.concurrent .

Kami melihat semantik yang menarik dari daftar ini dan bagaimana hal itu dapat diulang dengan cara yang aman untuk thread, sementara thread lain dapat terus memasukkan atau menghapus elemen darinya.

Penerapan semua contoh dan cuplikan kode ini dapat ditemukan di proyek GitHub - ini adalah proyek Maven, jadi semestinya mudah untuk mengimpor dan menjalankannya apa adanya.