BlockingDeque — 양방향 블로킹 큐 인터페이스

BlockingDeque — 양방향 블로킹 큐 인터페이스

BlockingDeque<E>Deque(양방향 큐)에 블로킹 연산을 더한 인터페이스예요. 요소를 꺼낼 때는 덱이 비어 있지 않게 될 때까지 기다리고, 요소를 넣을 때는 덱에 공간이 생길 때까지 기다려요. 스레드 안전한 생산자-소비자 구조에서 양쪽 끝을 모두 써야 할 때 유용해요.

출처: Java API Reference

본문

4가지 형태의 메서드

BlockingDeque의 메서드는 즉시 만족될 수 없지만 나중에는 만족될 수 있는 연산을 다루는 방식에 따라 4가지 형태가 있어요:

  1. 예외를 던지는 형태
  2. 특수 값을 반환하는 형태(연산에 따라 null 또는 false)
  3. 무기한 블로킹하는 형태(성공할 때까지 현재 스레드를 막음)
  4. 주어진 최대 시간까지만 블로킹하다 포기하는 형태

머리(Head) 요소

동작 예외 특수 값 블로킹 타임아웃
삽입 addFirst(e) offerFirst(e) putFirst(e) offerFirst(e, time, unit)
제거 removeFirst() pollFirst() takeFirst() pollFirst(time, unit)
검사 getFirst() peekFirst() 해당 없음 해당 없음

꼬리(Tail) 요소

동작 예외 특수 값 블로킹 타임아웃
삽입 addLast(e) offerLast(e) putLast(e) offerLast(e, time, unit)
제거 removeLast() pollLast() takeLast() pollLast(time, unit)
검사 getLast() peekLast() 해당 없음 해당 없음

주요 특성

어떤 BlockingQueue든 마찬가지로, BlockingDeque스레드 안전하고 null 요소를 허용하지 않으며, 용량 제한이 있을 수도 없을 수도 있어요.

BlockingDeque 구현체는 그대로 FIFO BlockingQueue 로도 쓸 수 있어요. BlockingQueue에서 상속받은 메서드는 BlockingDeque 메서드와 정확히 대응해요.

BlockingQueue 메서드 동등한 BlockingDeque 메서드
add(e) addLast(e)
offer(e) offerLast(e)
put(e) putLast(e)
offer(e, time, unit) offerLast(e, time, unit)
remove() removeFirst()
poll() pollFirst()
take() takeFirst()
poll(time, unit) pollFirst(time, unit)
element() getFirst()
peek() peekFirst()

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

삽입 메서드

void addFirst(E e) — 용량 제한을 위반하지 않고 즉시 가능하면 덱 앞에 삽입해요. 공간이 없으면 IllegalStateException을 던져요. 용량 제한이 있는 덱에서는 offerFirst를 쓰는 게 보통 좋아요.

  • IllegalStateException (용량 제한), ClassCastException, NullPointerException, IllegalArgumentException

void addLast(E e) — 덱 끝에 같은 방식으로 삽입해요. (addFirst와 동일한 예외)

boolean offerFirst(E e) — 즉시 가능하면 앞에 삽입하고 성공 시 true, 공간이 없으면 false를 반환해요. 예외로만 실패를 알리는 addFirst보다 선호돼요.

boolean offerLast(E e) — 끝에 같은 방식으로 삽입해요.

void putFirst(E e) throws InterruptedException — 공간이 생길 때까지 필요한 만큼 기다리며 앞에 삽입해요. 기다리는 동안 인터럽트되면 InterruptedException.

void putLast(E e) throws InterruptedException — 같은 방식으로 끝에 삽입해요.

boolean offerFirst(E e, long timeout, TimeUnit unit) throws InterruptedException — 공간이 생길 때까지 최대 timeout만큼 기다리며 앞에 삽입해요. 성공 시 true, 대기 시간이 지나면 false.

boolean offerLast(E e, long timeout, TimeUnit unit) throws InterruptedException — 끝에 같은 방식으로 삽입해요.

제거 메서드

E takeFirst() throws InterruptedException — 요소가 생길 때까지 기다리며 덱의 첫 요소를 꺼내 제거해요.

  • InterruptedException (대기 중 인터럽트)

E takeLast() throws InterruptedException — 요소가 생길 때까지 기다리며 마지막 요소를 꺼내 제거해요.

E pollFirst(long timeout, TimeUnit unit) throws InterruptedException — 요소가 생길 때까지 최대 timeout만큼 기다리며 첫 요소를 꺼내요. 시간이 지나면 null.

E pollLast(long timeout, TimeUnit unit) throws InterruptedException — 끝에 같은 방식으로 꺼내요.

boolean removeFirstOccurrence(Object o)o.equals(e)인 첫 번째 요소를 제거해요. 없으면 덱은 변하지 않아요. 결과적으로 요소가 제거됐으면 true.

  • ClassCastException, NullPointerException (선택)

boolean removeLastOccurrence(Object o) — 같은 방식으로 마지막 일치 요소를 제거해요.

FIFO 큐 관점 메서드 (Deque/Queue 인터페이스)

add/offer/put 는 각각 addLast/offerLast/putLast와 동등하고, remove/poll/take 는 각각 removeFirst/pollFirst/takeFirst와 동등해요. remove(o)removeFirstOccurrence와, element()getFirst와, peek()peekFirst와 동등해요.

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

  • IllegalStateException, ClassCastException, NullPointerException, IllegalArgumentException

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

int size() — 덱의 요소 개수를 반환해요.

Iterator<E> iterator() — 덱의 요소를 머리부터 꼬리 순서로 순회하는 iterator를 반환해요.

더 알아보기 (Learn more)