Java LinkedBlockingQueue 마스터: 완벽 가이드 & 실전 예제
Java LinkedBlockingQueue
LinkedBlockingQueue 클래스, 핵심 메서드, 실전 예제로 Java에서 스레드 안전 큐잉을 마스터하세요.
LinkedBlockingQueue 클래스는 Java의 java.util.concurrent 패키지에 속하며 연결 리스트로 뒷받침되는 블로킹 큐를 구현합니다. BlockingQueue 인터페이스를 준수하여 동시 생산자-소비자 시나리오에 적합한 견고한 스레드 안전 구조를 제공합니다.
LinkedBlockingQueue 생성하기
이 큐를 사용하려면 java.util.concurrent.LinkedBlockingQueue를 임포트하세요:
import java.util.concurrent.LinkedBlockingQueue;
1. 초기 용량 없이
LinkedBlockingQueue<Type> queue = new LinkedBlockingQueue<>();
기본 용량은 Integer.MAX_VALUE (231–1)로, 큐를 사실상 무제한으로 만듭니다.
2. 지정된 용량으로
LinkedBlockingQueue<Type> queue = new LinkedBlockingQueue<>(int capacity);
Type – 요소 타입 (예: String, Integer)
capacity – 큐가 담을 수 있는 최대 요소 수
예제:
// 용량 5 String 큐
LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5);
// 용량 5 Integer 큐
LinkedBlockingQueue<Integer> ages = new LinkedBlockingQueue<>(5);
참고: 용량은 선택 사항이며, 생략 시 무제한 큐가 생성됩니다.
LinkedBlockingQueue 주요 메서드
이 클래스는 요소 삽입, 검색, 제거를 위한 모든 BlockingQueue 메서드를 구현합니다. put()과 take() 두 메서드는 표준 큐와 구별되는 블로킹 동작을 제공합니다.
요소 삽입
add(E e) – 요소 추가, 큐가 가득 차면 예외 발생
offer(E e) – 요소 추가, 큐가 가득 차면 false 반환
예제:
import java.util.concurrent.LinkedBlockingQueue;
public class Main {
public static void main(String[] args) {
LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5);
animals.add("Dog");
animals.add("Cat");
animals.offer("Horse");
System.out.println("LinkedBlockingQueue: " + animals);
}
}
출력
LinkedBlockingQueue: [Dog, Cat, Horse]
요소 접근
peek() – 헤드 요소 조회(제거 안 함), 비어있으면 null
iterator() – 큐의 fail-safe 이터레이터 제공. 사용 위해 java.util.Iterator 임포트 필요
예제:
import java.util.concurrent.LinkedBlockingQueue;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5);
animals.add("Dog");
animals.add("Cat");
animals.add("Horse");
System.out.println("LinkedBlockingQueue: " + animals);
String head = animals.peek();
System.out.println("Accessed Element: " + head);
Iterator<String> it = animals.iterator();
System.out.print("LinkedBlockingQueue Elements: ");
while (it.hasNext()) {
System.out.print(it.next() + ", ");
}
}
}
출력
LinkedBlockingQueue: [Dog, Cat, Horse] Accessed Element: Dog LinkedBlockingQueue Elements: Dog, Cat, Horse,
요소 제거
remove() – 헤드 제거 및 반환, 비어있으면 예외
poll() – 헤드 제거 및 반환, 비어있으면 null
clear() – 모든 요소 제거
예제:
import java.util.concurrent.LinkedBlockingQueue;
public class Main {
public static void main(String[] args) {
LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5);
animals.add("Dog");
animals.add("Cat");
animals.add("Horse");
System.out.println("LinkedBlockingQueue: " + animals);
String removed = animals.remove();
System.out.println("Using remove(): " + removed);
String polled = animals.poll();
System.out.println("Using poll(): " + polled);
animals.clear();
System.out.println("Updated LinkedBlockingQueue: " + animals);
}
}
출력
LinkedBlockingQueue: [Dog, Cat, Horse] Using remove(): Dog Using poll(): Cat Updated LinkedBlockingQueue: []
블로킹 연산: put() & take()
동시성 컨텍스트에서 put()과 take()는 연산이 진행될 때까지 호출 스레드를 블로킹하여 생산자와 소비자 간 안전한 조정을 보장합니다.
put()
꼬리에 요소 삽입, 큐가 가득 차면 대기.
예제:
import java.util.concurrent.LinkedBlockingQueue;
public class Main {
public static void main(String[] args) {
LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5);
try {
animals.put("Dog");
animals.put("Cat");
System.out.println("LinkedBlockingQueue: " + animals);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.err.println(e.getMessage());
}
}
}
출력
LinkedBlockingQueue: [Dog, Cat]
take()
헤드 요소 검색 및 제거, 큐가 비어있으면 블로킹.
예제:
import java.util.concurrent.LinkedBlockingQueue;
public class Main {
public static void main(String[] args) {
LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5);
try {
animals.put("Dog");
animals.put("Cat");
System.out.println("LinkedBlockingQueue: " + animals);
String removed = animals.take();
System.out.println("Removed Element: " + removed);
System.out.println("New LinkedBlockingQueue: " + animals);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.err.println(e.getMessage());
}
}
}
출력
LinkedBlockingQueue: [Dog, Cat] Removed Element: Dog New LinkedBlockingQueue: [Cat]
추가 유틸리티 메서드
| 메서드 | 설명 |
contains(Object o) | 큐가 지정된 요소를 담고 있는지 확인 |
size() | 현재 요소 수 반환 |
toArray() | 큐를 배열로 변환 |
toString() | 큐의 문자열 표현 제공 |
왜 LinkedBlockingQueue를 선택하는가?
내부적으로 연결 리스트를 사용하므로 LinkedBlockingQueue는 다음을 제공합니다:
- 기본 제공 스레드 안전성
- 백프레셔 제어를 위한 선택적 고정 용량
- 생산자와 소비자를 자연스럽게 조정하는 블로킹 메서드
한 스레드가 다른 스레드보다 느리게 생산하는 멀티스레드 애플리케이션에서 큐는 새 아이템이 도착할 때까지 소비자를 자동으로 일시정지시켜 바쁜 대기를 방지하고 CPU 오버헤드를 줄입니다.
고성능 동시 워크로드에서 Java 동시성 API는 생산자-소비자 파이프라인의 필수 구조로 LinkedBlockingQueue를 권장합니다.