📅  最后修改于: 2023-12-03 15:39:08.322000             🧑  作者: Mango
CopyOnWriteArraySet 是 java.util.concurrent 包下的一个线程安全集合类,它是对 CopyOnWriteArrayList 的一个实现。CopyOnWriteArraySet 的底层实现是一个 CopyOnWriteArrayList 实例,所有的 add、remove、contains 等操作都是通过操作底层的 CopyOnWriteArrayList 实例完成的。CopyOnWriteArraySet 的主要特点是读写分离,读操作不用加锁,写操作需要加锁,保证了数据的一致性和线程安全。
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 的底层实现是 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 可以很方便地实现数据的读写分离,提高并发性能。