비차단 대기열

연결된 노드에서 스레드 안전하고 가장 중요한 비차단 Queue 구현.
ConcurrentLinkedQueue<E> - 가비지 수집기와 함께 작동하도록 조정된 대기 없는 알고리즘을 사용합니다. 이 알고리즘은 CAS를 기반으로 구축되었기 때문에 매우 효율적이고 매우 빠릅니다. size() 메서드는오랫동안 실행될 수 있으므로 항상 끌어오지 않는 것이 가장 좋습니다.
ConcurrentLinkedDeque<E> - Deque는 이중 종료 대기열을 나타냅니다. 이는 양쪽에서 데이터를 추가하고 가져올 수 있음을 의미합니다. 따라서 이 클래스는 FIFO(First In First Out) 및 LIFO(Last In First Out)의 두 가지 작동 모드를 모두 지원합니다.
실제로 LIFO가 절대적으로 필요한 경우 ConcurrentLinkedDeque를 사용해야 합니다. 노드의 양방향성으로 인해 이 클래스는 ConcurrentLinkedQueue 에 비해 성능이 절반으로 떨어지기 때문입니다 .
import java.util.concurrent.ConcurrentLinkedQueue;
public class ConcurrentLinkedQueueExample {
public static void main(String[] args) {
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
Thread producer = new Thread(new Producer(queue));
Thread consumer = new Thread(new Consumer(queue));
producer.start();
consumer.start();
}
}
class Producer implements Runnable {
ConcurrentLinkedQueue<String> queue;
Producer(ConcurrentLinkedQueue<String> queue){
this.queue = queue;
}
public void run() {
System.out.println("Class for adding items to the queue");
try {
for (int i = 1; i < 5; i++) {
queue.add("Item #" + i);
System.out.println("Added: Item #" + i);
Thread.sleep(300);
}
} catch (InterruptedException ex) {
ex.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
class Consumer implements Runnable {
ConcurrentLinkedQueue<String> queue;
Consumer(ConcurrentLinkedQueue<String> queue){
this.queue = queue;
}
public void run() {
String str;
System.out.println("Class for getting items from the queue");
for (int x = 0; x < 5; x++) {
while ((str = queue.poll()) != null) {
System.out.println("Pulled out: " + str);
}
try {
Thread.sleep(600);
} catch (InterruptedException ex) {
ex.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
}
차단 대기열

BlockingQueue<E> 인터페이스 - 데이터가 많으면 ConcurrentLinkedQueue 로는 부족합니다.
스레드가 작업을 수행하지 못하면 OutOfMemmoryException 을 쉽게 얻을 수 있습니다 . 이러한 경우가 발생하지 않도록 대기열 및 조건부 잠금을 채우고 작업하는 다양한 방법이 있는 작업을 위한 BlockingQueue가 있습니다.
BlockingQueue는 null 요소를 인식하지 못하고이러한 요소를 추가하거나 가져오려고 할 때 NullPointerException을 발생시킵니다. poll 메서드는 제한 시간 내에 대기열에 요소가 배치되지 않은 경우 null 요소를 반환합니다.
BlockingQueue<E> 구현
각 BlockingQueue 구현을 자세히 살펴보겠습니다 .
ArrayBlockingQueue<E>는 클래식 링 버퍼에 구축된 차단 대기열 클래스입니다. 여기에서 자물쇠의 "정직성"을 관리할 기회가 있습니다. fair=false(기본값)이면 스레드 순서가 보장되지 않습니다.
DelayQueue<E extends Delayed>는 Delayed 인터페이스 의 getDelay 메서드 를 통해 각 요소에 정의된 특정 지연 이후에만 대기열에서 요소를 가져올 수 있도록 하는 클래스입니다.
LinkedBlockingQueue<E> 는 "2개의 잠금 대기열" 알고리즘으로 구현된 연결된 노드의 차단 대기열입니다. 첫 번째 잠금은 추가용이고 두 번째 잠금은 대기열에서 요소를 가져오기 위한 것입니다. 잠금으로 인해 ArrayBlockingQueue 에 비해이 클래스는 성능이 높지만 더 많은 메모리가 필요합니다. 대기열 크기는 생성자를 통해 설정되며 기본적으로 Integer.MAX_VALUE와 같습니다.
PriorityBlockingQueue<E>는 PriorityQueue 에 대한 다중 스레드 래퍼입니다. Comparator는 요소가 추가되는 논리를 담당합니다. 가장 작은 요소가 먼저 나옵니다.
SynchronousQueue<E> - 대기열은 FIFO(선입선출) 원칙에 따라 작동합니다. 각 삽입 작업은 "소비자" 스레드가 대기열에서 요소를 가져올 때까지 "생산자" 스레드를 차단하고 그 반대의 경우도 마찬가지입니다. "소비자"는 "생산자"가 요소를 삽입할 때까지 대기합니다.
BlockingDeque<E>는 양방향 차단 대기열에 대한 추가 메서드를 설명하는 인터페이스입니다. 대기열의 양쪽에서 데이터를 삽입하고 꺼낼 수 있습니다.
LinkedBlockingDeque<E>는 하나의 잠금이 있는 간단한 양방향 목록으로 구현된 연결된 노드의 양방향 차단 대기열입니다. 대기열 크기는 생성자를 통해 설정되며 기본적으로 Integer.MAX_VALUE와 같습니다.
TransferQueue<E> - 요소가 대기열에 추가될 때다른 소비자 스레드가 대기열에서 요소를 가져올 때까지 삽입하는 생산자 스레드를 차단할 수 있다는 점에서 인터페이스가 흥미롭습니다. 특정 시간 제한에 대한 확인을 추가하거나 대기 중인 Consumer 에 대한 확인을 설정할 수도 있습니다. 결과적으로 비동기 및 동기 메시지를 지원하는 데이터 전송 메커니즘을 얻습니다.
LinkedTransferQueue<E>는 Dual Queues with Slack 알고리즘을 기반으로 하는 TransferQueue의 구현입니다유휴 상태일 때 CAS(위 참조) 및 스레드 파킹을 많이 사용합니다.
GO TO FULL VERSION