ConcurrentLinkedDeque — 무경계 동시성 양방향 큐

ConcurrentLinkedDeque — 무경계 동시성 양방향 큐

ConcurrentLinkedDeque<E>연결된 노드 기반의 무경계(unbounded) 동시성 덱(deque) 이에요. 여러 스레드가 같은 컬렉션을 동시에 안전하게 접근·삽입·제거해야 할 때 좋은 선택이에요. 양쪽 끝(머리/꼬리)을 모두 활용해야 하는 작업에 적합해요.

출처: Java API Reference

본문

개념 이해하기

ConcurrentLinkedDeque는 연결된 노드 기반의 무경계 동시성 덱이에요. 동시 삽입·제거·접근 연산이 여러 스레드에서 안전하게 실행돼요. 다른 대부분의 동시성 컬렉션처럼 null 요소를 허용하지 않아요.

public class ConcurrentLinkedDeque<E>
extends AbstractCollection<E>
implements Deque<E>, Serializable
  • iterator와 spliterator는 약하게 일관적(weakly consistent) 이에요.
  • size 메서드는 상수 시간 연산이 아니에요. 덱의 비동기 특성 때문에 현재 요소 수를 알려면 순회가 필요하고, 순회 중 컬렉션이 수정되면 부정확한 결과를 낼 수 있어요. 그래서 동시성 애플리케이션에서 크게 유용하지 않을 수 있어요.
  • addAll, removeIf, forEach 같은 일괄 연산은 원자적으로 수행된다는 보장이 없어요. 예를 들어 addAll과 동시에 도는 forEach는 추가된 요소의 일부만 관찰할 수 있어요.

메모리 일관성 효과: 다른 동시성 컬렉션처럼, 한 스레드가 ConcurrentLinkedDeque에 객체를 넣기 전의 동작은 다른 스레드가 그 요소를 접근·제거한 이후의 동작보다 happen-before 관계예요.

생성자

public ConcurrentLinkedDeque() — 빈 덱을 만들어요.

public ConcurrentLinkedDeque(Collection<? extends E> c) — 주어진 컬렉션의 iterator 순회 순서대로 요소를 담은 덱을 만들어요.

  • NullPointerException — 컬렉션 또는 요소가 null일 때

삽입 메서드

public void addFirst(E e) — 덱 앞에 요소를 삽입해요. 무경계이므로 IllegalStateException을 던지지 않아요.

  • NullPointerException

public void addLast(E e) — 덱 끝에 요소를 삽입해요. add(E)와 동등.

  • NullPointerException

public boolean offerFirst(E e) — 앞에 삽입해요. 무경계이므로 false를 반환하지 않아요.

public boolean offerLast(E e) — 끝에 삽입해요. add(E)와 동등.

public boolean offer(E e) — 꼬리에 삽입해요. 무경계이므로 false를 반환하지 않아요.

public boolean add(E e) — 꼬리에 삽입해요. 무경계이므로 IllegalStateException도 던지지 않고 false도 반환하지 않아요.

public void push(E e) — 덱을 스택처럼 쓰며 머리에 밀어 넣어요. (Deque.addFirst와 동등)

조회(비제거) 메서드

public E peekFirst() — 첫 요소를 제거하지 않고 반환하거나, 비어 있으면 null.

public E peekLast() — 마지막 요소를 제거하지 않고 반환하거나, 비어 있으면 null.

public E getFirst() — 첫 요소를 제거하지 않고 반환해요. peekFirst와 달리 비어 있으면 예외를 던져요.

  • NoSuchElementException (비어 있을 때)

public E getLast() — 마지막 요소를 반환. peekLast와 달리 비어 있으면 예외.

public E peek() — 큐의 머리를 제거하지 않고 반환하거나 null. (Deque.peekFirst와 동등)

public E element() — 큐의 머리를 제거하지 않고 반환. peek와 달리 비어 있으면 예외.

제거 메서드

public E pollFirst() — 첫 요소를 꺼내 제거하거나, 비어 있으면 null.

public E pollLast() — 마지막 요소를 꺼내 제거하거나, 비어 있으면 null.

public E removeFirst() — 첫 요소를 꺼내 제거해요. pollFirst와 달리 비어 있으면 예외.

  • NoSuchElementException

public E removeLast() — 마지막 요소를 꺼내 제거해요. 비어 있으면 예외.

public E poll() — 첫 요소를 꺼내거나 null. (Deque.pollFirst와 동등)

public E remove() — 첫 요소를 꺼내 제거해요. 비어 있으면 예외. (Deque.removeFirst와 동등)

public E pop() — 스택에서 요소를 꺼내요(첫 요소를 제거·반환). (Deque.removeFirst와 동등)

public boolean removeFirstOccurrence(Object o)o.equals(e)인 첫 번째 요소를 제거해요. 덱이 변했으면 true.

  • NullPointerException

public boolean removeLastOccurrence(Object o) — 마지막 일치 요소를 제거해요.

public boolean remove(Object o) — 첫 번째 일치 요소를 제거해요. (removeFirstOccurrence(Object)와 동등)

기타 컬렉션 메서드

public boolean contains(Object o)o.equals(e)인 요소를 하나 이상 담고 있으면 true.

public boolean isEmpty() — 요소가 없으면 true.

public int size() — 요소 수를 반환해요. Integer.MAX_VALUE를 넘으면 Integer.MAX_VALUE. 상수 시간이 아니며 순회로 세므로 동시성 앱에서 크게 유용하지 않아요.

public boolean addAll(Collection<? extends E> c) — 주어진 컬렉션의 요소를 덱 끝에 순서대로 더해요. 덱을 자기 자신에 addAll하면 IllegalArgumentException.

  • NullPointerException, IllegalArgumentException

public void clear() — 모든 요소를 제거해요.

public Object[] toArray() — 머리부터 꼬리 순서의 요소를 담은 새 배열을 반환해요.

public <T> T[] toArray(T[] a) — 요소를 지정 배열에 담아 반환해요. 크기가 맞으면 그 배열에, 아니면 같은 런타임 타입의 새 배열에요. ArrayStoreException, NullPointerException.

public boolean removeIf(Predicate<? super E> filter) — 주어진 술어를 만족하는 요소를 모두 제거해요.

  • NullPointerException — 필터가 null일 때

public boolean removeAll(Collection<?> c), public boolean retainAll(Collection<?> c), public void forEach(Consumer<? super E> action) — 표준 컬렉션 연산들.

iterator/spliterator

public Iterator<E> iterator() — 머리부터 꼬리 순서의 약하게 일관적 iterator를 반환해요.

public Iterator<E> descendingIterator() — 꼬리부터 머리 순서의 역순 iterator를 반환해요.

public Spliterator<E> spliterator() — 약하게 일관적인 spliterator를 반환해요. CONCURRENT, ORDERED, NONNULL을 보고하며, trySplit으로 제한된 병렬 처리를 지원해요. (JDK 1.8+)

더 알아보기 (Learn more)