CopyOnWriteArraySet — 쓰기 시 복사 동시성 셋
CopyOnWriteArraySet — 쓰기 시 복사 동시성 셋
CopyOnWriteArraySet<E>는 모든 연산에 내부 CopyOnWriteArrayList를 사용하는 Set이에요. 읽기가 압도적으로 많고 변경이 드문 작은 셋에 적합한 스레드 안전한 구현이에요.
본문
개념 이해하기
CopyOnWriteArraySet은 모든 연산에 내부 CopyOnWriteArrayList를 사용하는 Set이에요. 그래서 같은 기본 속성을 공유해요.
public class CopyOnWriteArraySet<E>
extends AbstractSet<E>
implements Serializable
- 셋 크기가 일반적으로 작고, 읽기 전용 연산이 변경 연산을 압도적으로 많이 앞서며, 순회 중 스레드 간 간섭을 막아야 하는 애플리케이션에 가장 적합해요.
- 스레드 안전해요.
- 변경 연산(
add,set,remove등)은 비싸요 — 보통 전체 내부 배열을 복사하기 때문이에요. - iterator는 변경적
remove연산을 지원하지 않아요. - iterator를 통한 순회는 빠르고 다른 스레드의 간섭을 만날 수 없어요 — iterator는 생성 시점의 변하지 않는 배열 스냅샷에 의존해요.
활용 예
class Handler { void handle() { ... } }
class X {
private final CopyOnWriteArraySet<Handler> handlers
= new CopyOnWriteArraySet<>();
public void addHandler(Handler h) { handlers.add(h); }
private long internalState;
private synchronized void changeState() { internalState = ...; }
public void update() {
changeState();
for (Handler handler : handlers)
handler.handle();
}
}
생성자
public CopyOnWriteArraySet() — 빈 셋을 만들어요.
public CopyOnWriteArraySet(Collection<? extends E> c) — 주어진 컬렉션의 모든 요소를 담은 셋을 만들어요.
NullPointerException
기본 연산
public int size() / public boolean isEmpty() — 표준.
public boolean contains(Object o) — Objects.equals(o, e)인 요소가 있으면 true.
public boolean add(E e) — 같은 요소가 없으면 추가해요. 이미 있으면 셋을 바꾸지 않고 false.
public boolean remove(Object o) — 요소가 있으면 제거해요. 제거됐으면 true.
public void clear() — 모든 요소를 제거해요.
일괄 연산
public boolean containsAll(Collection<?> c) — 모든 요소 포함 시 true. 컬렉션이 셋이면 부분집합 여부. NullPointerException.
public boolean addAll(Collection<? extends E> c) — 아직 없는 요소만 추가해요(합집합 효과). NullPointerException.
public boolean removeAll(Collection<?> c) — 포함된 요소를 모두 제거해요(비대칭 차집합 효과).
public boolean retainAll(Collection<?> c) — 포함된 요소만 남겨요(교집합 효과).
public boolean removeIf(Predicate<? super E> filter) / public void forEach(Consumer<? super E> action) — 표준 컬렉션 연산.
public boolean equals(Object o) — 같은 Set이고 같은 요소면 true.
iterator/spliterator
public Iterator<E> iterator() — 요소가 추가된 순서대로 요소를 반환하는 iterator. 생성 시점 스냅샷이며 순회 중 동기화가 필요 없고, remove를 지원하지 않아요.
public Spliterator<E> spliterator() — 추가된 순서대로 IMMUTABLE, DISTINCT, SIZED, SUBSIZED를 보고하는 spliterator. 생성 시점 스냅샷. (JDK 1.8+)