ConcurrentLinkedQueue를 사용하는 방법?
ConcurrentLinkedQueue
Java에서를 어떻게 사용 합니까?
이것을 사용 LinkedQueue
하면 대기열의 동시성에 대해 걱정해야합니까? 아니면 두 가지 메서드를 정의해야합니까 (하나는 목록에서 요소를 검색하고 다른 하나는 목록에 요소를 추가하는 것)?
참고 : 분명히이 두 가지 방법은 동기화되어야합니다. 권리?
편집 : 내가하려는 것은 이것입니다 : 대기열에서 항목을 검색하는 한 가지 방법이있는 클래스 (Java)와 대기열에 항목을 추가하는 한 가지 방법이있는 다른 클래스가 있습니다. 목록에서 추가 및 검색된 항목은 내 클래스의 개체입니다.
한 가지 더 질문 : remove 메서드에서이 작업을 수행해야합니까?
while (queue.size() == 0){
wait();
queue.poll();
}
소비자와 생산자는 한 명뿐입니다.
아니요, 메서드를 동기화 할 필요가 없으며 메서드를 정의 할 필요가 없습니다. 이미 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.
Everything else is the same. Put probably won't block, because you aren't likely to put two billion objects into the queue.
This is largely a duplicate of another question.
Here's the section of that answer that is relevant to this question:
Do I need to do my own synchronization if I use java.util.ConcurrentLinkedQueue?
Atomic operations on the concurrent collections are synchronized for you. In other words, each individual call to the queue is guaranteed thread-safe without any action on your part. What is not guaranteed thread-safe are any operations you perform on the collection that are non-atomic.
For example, this is threadsafe without any action on your part:
queue.add(obj);
or
queue.poll(obj);
However; non-atomic calls to the queue are not automatically thread-safe. For example, the following operations are not automatically threadsafe:
if(!queue.isEmpty()) {
queue.poll(obj);
}
That last one is not threadsafe, as it is very possible that between the time isEmpty is called and the time poll is called, other threads will have added or removed items from the queue. The threadsafe way to perform this is like this:
synchronized(queue) {
if(!queue.isEmpty()) {
queue.poll(obj);
}
}
Again...atomic calls to the queue are automatically thread-safe. Non-atomic calls are not.
Use poll to get the first element, and add to add a new last element. That's it, no synchronization or anything else.
This is probably what you're looking for in terms of thread safety & "prettyness" when trying to consume everything in the queue:
for (YourObject obj = queue.poll(); obj != null; obj = queue.poll()) {
}
This will guarantee that you quit when the queue is empty, and that you continue to pop objects off of it as long as it's not empty.
The ConcurentLinkedQueue is a very efficient wait/lock free implementation (see the javadoc for reference), so not only you don't need to synchronize, but the queue will not lock anything, thus being virtually as fast as a non synchronized (not thread safe) one.
Just use it as you would a non-concurrent collection. The Concurrent[Collection] classes wrap the regular collections so that you don't have to think about synchronizing access.
Edit: ConcurrentLinkedList isn't actually just a wrapper, but rather a better concurrent implementation. Either way, you don't have to worry about synchronization.
참고URL : https://stackoverflow.com/questions/616484/how-to-use-concurrentlinkedqueue
'program story' 카테고리의 다른 글
Breadth-First Search에서 경로를 추적하는 방법은 무엇입니까? (0) | 2020.09.07 |
---|---|
Android Studio 게스트가 7 초 내에 온라인 상태가되지 않습니다. (0) | 2020.09.07 |
jQuery의 이벤트 핸들러에 인수를 어떻게 전달할 수 있습니까? (0) | 2020.09.07 |
파이썬에서 목록을 채우는 내장 (0) | 2020.09.07 |
Amazon RDS 백업 / 스냅 샷은 실제로 어떻게 작동합니까? (0) | 2020.09.06 |