본문으로 건너뛰기
김신건의 로그

[Java] ArrayBlockingQueue

· 수정 · 📖 약 1분 · 280자/단어 #java #concurrent #queue #blocking #bounded
ArrayBlockingQueue, java.util.concurrent.ArrayBlockingQueue, ABQ, 고정 크기 블로킹 큐

정의

java.util.concurrent.ArrayBlockingQueue<E>고정 크기 원형 배열 기반의 BlockingQueue. 생성 시 capacity 를 지정해야 하고 그 이상 늘어나지 않는다.

내부에 단일 ReentrantLock 을 사용 (head/tail 공유). 동시 throughput 은 LinkedBlockingQueue 보다 낮을 수 있지만 메모리 사용량이 예측 가능하고 GC 압력이 작다.

시각화

내부 구조

public class ArrayBlockingQueue<E> ... {
    final Object[] items;          // 원형 배열
    int takeIndex;                  // head
    int putIndex;                   // tail (next slot)
    int count;
    final ReentrantLock lock;
    private final Condition notEmpty;
    private final Condition notFull;
}

notEmpty, notFullReentrantLock Condition 을 사용. take 가 비어 있으면 notEmpty 에서 대기, put 이 가득 차면 notFull 에서 대기.

동작

public void put(E e) throws InterruptedException {
    lock.lockInterruptibly();
    try {
        while (count == items.length) notFull.await();      // 가득 차면 대기
        enqueue(e);
        notEmpty.signal();                                    // take 대기자 깨움
    } finally { lock.unlock(); }
}

public E take() throws InterruptedException {
    lock.lockInterruptibly();
    try {
        while (count == 0) notEmpty.await();                // 비어 있으면 대기
        E e = dequeue();
        notFull.signal();                                     // put 대기자 깨움
        return e;
    } finally { lock.unlock(); }
}

복잡도

작업시간
put, takeO(1)
offer, poll, peekO(1)
contains, remove(Object)O(n)
순회O(n), weakly consistent

ArrayBlockingQueue vs LinkedBlockingQueue

항목ArrayBlockingQueueLinkedBlockingQueue
크기항상 boundedoptionally bounded
백킹원형 배열linked list
단일 ReentrantLocktakeLock + putLock 분리
동시 throughput낮음 (락 경합)높음
메모리 / 원소슬롯 1개노드 객체 1개
GC 압력작음 (배열 고정)큼 (노드 생성/소멸)
공정성 옵션

IMPORTANT

메모리 예측이 중요한 환경, 또는 capacity 가 작은 경우 ArrayBlockingQueue 가 자연스럽다. 대량 throughput 이 필요하면 LinkedBlockingQueue.

사용 예

bounded 생산자-소비자

BlockingQueue<Task> queue = new ArrayBlockingQueue<>(100);

// Producer
new Thread(() -> {
    while (running) queue.put(create());
}).start();

// Consumer
new Thread(() -> {
    while (running) process(queue.take());
}).start();

참고

이 글의 용어 (4개)
[Java] BlockingQueuejava
정의 는 요소를 가져올 때 비어 있으면 대기, 넣을 때 가득 차 있으면 대기 하는 thread-safe 큐 인터페이스. 생산자-소비자 (producer-consumer) 패턴의 …
[Java] LinkedBlockingQueuejava
정의 는 linked list 기반의 . 기본 unbounded ( ) 이지만 생성 시 capacity 지정 가능. Two-Lock Queue 알고리즘 으로 producer 와 …
[Java] ReentrantLockjava
정의 는 키워드와 같은 상호 배제 (mutual exclusion) 를 제공하는 클래스 기반 락. JSR-166 (Java 5) 에서 추가됐다. "재진입 (reentrant)" …
Blocking (블로킹)concurrency
정의 Blocking 은 호출이 결과가 준비될 때까지 호출 스레드를 멈춰두는 실행 방식. 멈춰 있는 동안 그 스레드는 다른 일을 할 수 없다. OS 가 스레드를 sleep 상태로…

이 개념을 다룬 위키 페이지 (1)

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기