📜  实现 CopyOnWriteArraySet API 的Java程序(1)

📅  最后修改于: 2023-12-03 15:39:08.322000             🧑  作者: Mango

CopyOnWriteArraySet 简介

CopyOnWriteArraySet 是 java.util.concurrent 包下的一个线程安全集合类,它是对 CopyOnWriteArrayList 的一个实现。CopyOnWriteArraySet 的底层实现是一个 CopyOnWriteArrayList 实例,所有的 add、remove、contains 等操作都是通过操作底层的 CopyOnWriteArrayList 实例完成的。CopyOnWriteArraySet 的主要特点是读写分离,读操作不用加锁,写操作需要加锁,保证了数据的一致性和线程安全。

CopyOnWriteArraySet API

CopyOnWriteArraySet 继承自 AbstractSet 类,实现了 Set 接口,提供了如下常用方法:

构造方法
public CopyOnWriteArraySet() 
public CopyOnWriteArraySet(Collection<? extends E> c) 
基本操作方法
public int size() 
public boolean isEmpty() 
public boolean contains(Object o) 
public boolean add(E e) 
public boolean remove(Object o) 
高级操作方法
public Object[] toArray() 
public <T> T[] toArray(T[] a) 
public boolean removeAll(Collection<?> c) 
public boolean retainAll(Collection<?> c) 
public void clear() 
public Spliterator<E> spliterator()

实现 CopyOnWriteArraySet API 的 Java 程序

CopyOnWriteArraySet 的底层实现是 CopyOnWriteArrayList,因此我们需要先了解 CopyOnWriteArrayList。CopyOnWriteArrayList 的底层是一个数组,每次修改操作都会创建一个新数组,把修改后的数据复制进去,然后使用新数组替换旧数组,这样做的好处是,在不影响并发读的情况下,保证写操作的线程安全。CopyOnWriteArraySet 基于 CopyOnWriteArrayList,主要是对 add、remove、contains 等方法做了一些封装,具体实现如下:

import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteArraySet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable {

    private static final long serialVersionUID = 5458959060215461841L;
    private transient final CopyOnWriteArrayList<E> al;

    public CopyOnWriteArraySet() {
        al = new CopyOnWriteArrayList<E>();
    }
    
    public CopyOnWriteArraySet(Collection<? extends E> c) {
        al = new CopyOnWriteArrayList<E>();
        addAll(c);
    }
    
    public int size() {
        return al.size();
    }
    
    public boolean isEmpty() {
        return al.isEmpty();
    }

    public boolean contains(Object o) {
        return al.contains(o);
    }

    public boolean add(E e) {
        return al.addIfAbsent(e);
    }

    public boolean remove(Object o) {
        return al.remove(o);
    }

    public void clear() {
        al.clear();
    }
    
    public Spliterator<E> spliterator() {
        return al.spliterator();
    }
    
    public Object[] toArray() {
        return al.toArray();
    }
    
    public <T> T[] toArray(T[] a) {
        return al.toArray(a);
    }
    
    public boolean retainAll(Collection<?> c) {
        return al.retainAll(c);
    }
    
    public boolean removeAll(Collection<?> c) {
        return al.removeAll(c);
    }
    
    public String toString() {
        return al.toString();
    }

    public boolean equals(Object o) {
        return al.equals(o);
    }

    public int hashCode() {
        return al.hashCode();
    }

    public Iterator<E> iterator() {
        return al.iterator();
    }
    
    public Object clone() {
        try {
            @SuppressWarnings("unchecked")
            CopyOnWriteArraySet<E> clone = (CopyOnWriteArraySet<E>) super.clone();
            clone.al = new CopyOnWriteArrayList<E>(al);
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        }
    }
    
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException{
        s.defaultWriteObject();
        s.writeObject(al.toArray());
    }
    
    private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
        s.defaultReadObject();
        al = new CopyOnWriteArrayList<E>(s.readObject());
    }
}

上述程序中我们可以看到,CopyOnWriteArraySet 是通过对 CopyOnWriteArrayList 做了一些封装实现的,在 add、remove、contains 等操作中调用了底层的 CopyOnWriteArrayList 对应的方法,add、remove 方法调用了 CopyOnWriteArrayList 的 addIfAbsent、remove 方法来实现。

此外,CopyOnWriteArraySet 实现了接口 Set,所以我们可以像使用 Set 一样来使用 CopyOnWriteArraySet。如果需要使用迭代器,可以调用 CopyOnWriteArrayList 实例的 iterator 方法,如果需要支持高级操作(如 removeAll、retainAll 等),可以调用 CopyOnWriteArrayList 实例的对应方法。

这里还需要注意的地方是,在序列化和反序列化的时候,需要对 CopyOnWriteArraySet 进行特殊处理,即需要对底层的 CopyOnWriteArrayList 进行序列化和反序列化,否则会抛出异常。

结语

CopyOnWriteArraySet 是一个非常有用的集合类,在实现并发操作的时候,可以保证线程安全。使用 CopyOnWriteArraySet 可以很方便地实现数据的读写分离,提高并发性能。