아니요, 메서드를 동기화 할 필요가 없으며 메서드를 정의 할 필요가 없습니다. 이미 ConcurrentLinkedQueue에 있으므로 사용하면됩니다. ConcurrentLinkedQueue는 내부적으로 필요한 모든 잠금 및 기타 작업을 수행합니다. 생산자는 대기열에 데이터를 추가하고 소비자는 데이터를 폴링합니다.
먼저 대기열을 만듭니다.
Queue<YourObject> queue = new ConcurrentLinkedQueue<YourObject>();
이제 생산자 / 소비자 객체를 생성 할 때마다 대기열을 전달하여 객체를 넣을 어딘가에 있도록합니다 (대신 setter를 사용할 수 있지만 생성자에서 이런 종류의 작업을 수행하는 것을 선호합니다).
YourProducer producer = new YourProducer(queue);
과:
YourConsumer consumer = new YourConsumer(queue);
생산자에 항목을 추가하십시오.
queue.offer(myObject);
소비자에서 물건을 꺼내십시오 (큐가 비어 있으면 poll ()이 null을 반환하므로 확인하십시오).
YourObject myObject = queue.poll();
자세한 정보 는 Javadoc을 참조하십시오 .
편집하다:
큐가 비어 있지 않을 때까지 기다리는 것을 차단해야하는 경우 LinkedBlockingQueue 를 사용하는 것이 좋습니다. 를 사용하고 take () 메서드 . 그러나 LinkedBlockingQueue에는 최대 용량 (기본값은 Integer.MAX_VALUE, 20 억 이상)이 있으므로 상황에 따라 적절하지 않을 수도 있습니다.
하나의 스레드 만 대기열에 항목을 넣고 다른 스레드가 대기열에서 항목을 가져 오는 경우 ConcurrentLinkedQueue는 아마도 과잉 일 것입니다. 동시에 수백 또는 수천 개의 스레드가 대기열에 액세스 할 수있는 경우에 더 적합합니다. 다음을 사용하여 요구 사항을 충족 할 수 있습니다.
Queue<YourObject> queue = Collections.synchronizedList(new LinkedList<YourObject>());
이것의 장점은 인스턴스 (대기열)에서 잠기므로 복합 작업의 원 자성을 보장하기 위해 대기열에서 동기화 할 수 있다는 것입니다 (Jared가 설명 함). 모든 작업이 인스턴스에 대한 잠금없이 수행되므로 (java.util.concurrent.atomic 변수 사용) ConcurrentLinkedQueue로는이를 수행 할 수 없습니다. 큐가 비어있는 동안 차단하려면이 작업을 수행 할 필요가 없습니다. poll ()은 큐가 비어있는 동안 단순히 null을 반환하고 poll ()은 원자 적이기 때문입니다. poll ()이 null을 반환하는지 확인하십시오. 그렇다면 wait () 다음 다시 시도하십시오. 잠글 필요가 없습니다.
드디어:
솔직히 LinkedBlockingQueue를 사용합니다. 응용 프로그램에는 여전히 과잉이지만 잘 작동 할 가능성이 있습니다. 성능이 충분하지 않으면 (PROFILE!), 언제든지 다른 것을 시도 할 수 있으며 동기화 된 항목을 다룰 필요가 없음을 의미합니다.
BlockingQueue<YourObject> queue = new LinkedBlockingQueue<YourObject>();
queue.put(myObject); // Blocks until queue isn't full.
YourObject myObject = queue.take(); // Blocks until queue isn't empty.
다른 모든 것은 동일합니다. 넣어 아마 당신은 가능성이 대기열에 억 객체를 넣어하지 않기 때문에, 차단하지 않습니다.