BlockingDeque — 양방향 블로킹 큐 인터페이스
BlockingDeque — 양방향 블로킹 큐 인터페이스
BlockingDeque<E>는 Deque(양방향 큐)에 블로킹 연산을 더한 인터페이스예요. 요소를 꺼낼 때는 덱이 비어 있지 않게 될 때까지 기다리고, 요소를 넣을 때는 덱에 공간이 생길 때까지 기다려요. 스레드 안전한 생산자-소비자 구조에서 양쪽 끝을 모두 써야 할 때 유용해요.
본문
4가지 형태의 메서드
BlockingDeque의 메서드는 즉시 만족될 수 없지만 나중에는 만족될 수 있는 연산을 다루는 방식에 따라 4가지 형태가 있어요:
- 예외를 던지는 형태
- 특수 값을 반환하는 형태(연산에 따라
null또는false) - 무기한 블로킹하는 형태(성공할 때까지 현재 스레드를 막음)
- 주어진 최대 시간까지만 블로킹하다 포기하는 형태
머리(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를 반환해요.