openplanning

Hướng dẫn và ví dụ Java CopyOnWriteArrayList

  1. CopyOnWriteArrayList

1. CopyOnWriteArrayList

CopyOnWriteArrayList là một biến thể an toàn theo luồng (thread-safe) của ArrayList. Cũng giống như ArrayList, CopyOnWriteArray quản lý một mảng để lưu trữ các phần tử của nó, điều khác biệt là tất cả các hoạt động gây đột biến như add, set, remove, clear,... đều tạo ra một bản sao mới của mảng mà nó đang quản lý.
public class CopyOnWriteArrayList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
Hãy xem điều gì xẩy ra khi thêm một phần tử vào CopyOnWriteArrayList:
Chi phí để sử dụng CopyOnWriteArrayList là rất đắt đỏ, bạn phải trả giá nhiều hơn cho tài nguyên và hiệu xuất. Tuy nhiên CopyOnWriteArrayList có ích khi bạn không thể hoặc không muốn đồng bộ hoá khi đi ngang qua (traversal) các phần tử của danh sách.
Để dễ hiểu hãy xem xét một tình huống hai Thread sử dụng cùng một đối tượng List. Trong thời gian Thread-A đi ngang qua (traversal) các phần tử của List nó sẽ đóng băng các hoạt động chèn hoặc cập nhập trên List để có được dữ liệu toàn vẹn, nhưng rõ ràng điều này ảnh hưởng tới các hoạt động của Thread-B.
Khi bạn tạo ra đối tượng Iterator từ CopyOnWriteArrayList, nó sẽ giúp bạn đi ngang qua các phần tử của mảng hiện thời (lúc Iterator được tạo ra), các phần tử của mảng này sẽ không thay đổi trong suốt quá trình tồn tại của Iterator. Điều này có được vì bất cứ hoạt động add, set, remove, clear, .. nào trên CopyOnWriteArrayList sẽ tạo ra một mảng khác là bản sao của mảng hiện tại.
CopyOnWriteArrayListEx.java
package org.o7planning.copyonwritearraylist.ex;

import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteArrayListEx {

    public static void main(String[] args) {
        // Create a CopyOnWriteArrayList object:
        List<String> list = new CopyOnWriteArrayList<String>();
        list.add("A");
        list.add("B");
        list.add("C");
        
        Iterator<String> iterator1 = list.iterator();
        
        list.add("X1");
        list.add("X2");
        
        Iterator<String> iterator2 = list.iterator();
        
        System.out.println("--- Iterator 1: -----");
        while(iterator1.hasNext()) {
            System.out.println(iterator1.next());
        }
        
        System.out.println("--- Iterator 2: -----");
        while(iterator2.hasNext()) {
            System.out.println(iterator2.next());
        }
    }
}
Output:
--- Iterator 1: -----
A
B
C
--- Iterator 2: -----
A
B
C
X1
X2
Các hoạt động thay đổi phần tử trên chính các Iterator(add, set, remove) không được hỗ trợ. Các phương thức này ném ra UnsupportedOperationException.
Stream
Di chuyển qua (traversal) các phần tử của CopyOnWriteArrayList thông qua Stream cũng có kết quả giống với Iterator.
CopyOnWriteArrayListEx2.java
package org.o7planning.copyonwritearraylist.ex;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Stream;

public class CopyOnWriteArrayListEx2 {

    public static void main(String[] args) {
        // Create a CopyOnWriteArrayList object:
        List<String> list = new CopyOnWriteArrayList<String>();
        list.add("A");
        list.add("B");
        list.add("C");
        
        Stream<String> stream1 = list.stream();
        
        list.add("X1");
        list.add("X2");
        
        Stream<String> stream2 = list.stream();
        
        System.out.println("--- Stream 1: -----");
        stream1.forEach(System.out::println);
        
        System.out.println("--- Stream 2: -----");
        stream2.forEach(System.out::println);
    }
}
Output:
--- Stream 1: -----
A
B
C
--- Stream 2: -----
A
B
C
X1
X2
Ngoài các đặc điểm đặc biệt đã được đề cập ở trên CopyOnWriteArrayList cũng là một List thông thường, bạn có thể tìm thấy các ví dụ khác về List trong bài viết dưới đây:

Các hướng dẫn Java Collections Framework

Show More