source

Concurrent Linked Queue 사용방법

lovecheck 2023. 1. 2. 22:42
반응형

Concurrent Linked Queue 사용방법

★★★★★의 ConcurrentLinkedQueue★★★★★★★★★★★★★★★★★?
「」를 해 주세요.LinkedQueue의의동동동 정정?? ??? ???또는 두 가지 방법(목록에서 요소를 검색하고 목록에 요소를 추가하는 방법)만 정의하면 됩니까?
주의: 이 두 가지 방법은 동기화해야 합니다. ★★★★★★★★★★★★★★★★.


편집: 제가 하려는 것은 다음과 같습니다.큐에서 아이템을 취득하는 메서드와 큐에 아이템을 추가하는 메서드가 있는 클래스(Java)가 있습니다.목록에서 추가 및 검색된 항목은 내 클래스의 객체입니다.

한 가지 더 묻겠습니다.삭제 방법으로 해야 하나요?

while (queue.size() == 0){ 
  wait(); 
  queue.poll();
}

나는 소비자 한 명과 생산자 한 명밖에 없다.

아니요. 메서드는 동기화할 필요가 없으며 메서드를 정의할 필요도 없습니다.이미 ConcurrentLinkedQueue에 있습니다.그냥 사용하세요.Concurrent Linked Queue는 내부적으로 필요한 모든 잠금 및 기타 작업을 수행합니다.프로듀서가 큐에 데이터를 추가하고 소비자가 폴링합니다.

먼저 큐를 만듭니다.

Queue<YourObject> queue = new ConcurrentLinkedQueue<YourObject>();

이제 생산자/소비자 개체를 생성할 때 큐에 전달하여 개체를 저장할 수 있도록 하십시오(대신 세터를 사용할 수 있지만, 저는 이러한 작업을 컨스트럭터에서 수행하는 것이 좋습니다).

YourProducer producer = new YourProducer(queue);

또, 다음과 같이 합니다.

YourConsumer consumer = new YourConsumer(queue);

PD에 추가해 주세요.

queue.offer(myObject);

그리고 컨슈머에서 데이터를 꺼냅니다(큐가 비어 있는 경우 poll()은 늘을 반환하므로 확인하십시오).

YourObject myObject = queue.poll();

자세한 내용은 Javadoc을 참조하십시오.

편집:

큐가 비워지지 않을 때까지 대기하는 것을 차단해야 하는 경우 Linked Blocking Queue를 사용하여 take() 메서드를 사용할 수 있습니다.그러나 LinkedBlockingQueue에는 최대 용량이 있습니다(기본값은 Integer).MAX_VALUE, 즉 20억을 초과하므로 상황에 따라 적절하지 않을 수도 있습니다.

큐에 데이터를 저장하는 스레드가 1개뿐이고 큐에서 데이터를 가져오는 스레드가 다른 스레드일 경우 Concurrent Linked Queue는 오버킬일 수 있습니다.동시에 큐에 액세스하는 스레드가 수백 개 또는 수천 개에 달할 때를 위한 것입니다.다음과 같은 방법으로 고객의 요구를 충족시킬 수 있습니다.

Queue<YourObject> queue = Collections.synchronizedList(new LinkedList<YourObject>());

게다가 인스턴스(큐)에서 잠기므로 큐에서 동기화하여 복합 조작의 원자성을 확보할 수 있습니다(Jared 설명).모든 작업은 instance에서 잠금 없이 수행되므로 ConcurrentLinkedQueue에서는 수행할 수 없습니다(java.util.concurrent.atomic 변수 사용).poll()은 단순히 큐가 비어 있는 동안 null을 반환하고 poll()은 atomic을 반환하기 때문에 큐가 비어 있는 동안 차단할 필요가 없습니다.poll()이 null을 반환하는지 확인합니다.문제가 있는 경우는, 대기()하고 나서 다시 시도합니다.잠글 필요 없어요.

마지막으로:

솔직히 Linked Blocking Queue를 사용합니다.당신의 어플리케이션에는 아직 과잉이지만, 아마 정상적으로 동작할 것입니다.퍼포먼스가 충분하지 않은 경우(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.

다른 건 다 똑같아요.20억개의 오브젝트를 큐에 넣을 가능성은 낮기 때문에 put은 차단되지 않을 수 있습니다.

이것은 대체로 다른 질문의 복제품이다.

다음은 이 질문에 관련된 답변의 섹션입니다.

java.util을 사용하는 경우 자체 동기화를 수행해야 합니까?Concurrent Linked Queue?

동시 컬렉션의 원자성 작업이 동기화됩니다.즉, 큐에 대한 각 개별 콜은 사용자의 조작 없이 스레드 세이프가 보증됩니다.스레드 세이프가 보장되지 않는 것은 수집에 대해 실행하는 비원자적인 조작입니다.

예를 들어, 이것은 사용자가 아무런 조치를 취하지 않아도 스레드 세이프입니다.

queue.add(obj);

또는

queue.poll(obj);

단, 큐에 대한 비원자 콜은 자동으로 스레드 세이프가 되지 않습니다.예를 들어, 다음 작업은 자동으로 스레드 세이프가 되지 않습니다.

if(!queue.isEmpty()) {
   queue.poll(obj);
}

마지막 스레드는 스레드 세이프가 아닙니다.이는 is Empty가 호출된 시간과 폴링이 호출된 시간 사이에 다른 스레드가 큐에서 항목을 추가 또는 삭제했을 가능성이 매우 높기 때문입니다.스레드 세이프 방법은 다음과 같습니다.

synchronized(queue) {
    if(!queue.isEmpty()) {
       queue.poll(obj);
    }
}

다시 말씀드리지만 큐에 대한 원자 호출은 자동으로 스레드 세이프가 됩니다.비원자적 통화는 그렇지 않습니다.

큐내의 모든 것을 소비하려고 할 때의 스레드의 안전성과 「예쁘다」의 관점에서, 다음과 같은 것을 요구하고 있습니다.

for (YourObject obj = queue.poll(); obj != null; obj = queue.poll()) {
}

이렇게 하면 큐가 비어 있을 때 종료되고 큐가 비어 있지 않은 한 오브젝트를 계속 팝업할 수 있습니다.

첫 번째 요소를 가져오려면 폴링을 사용하고, 마지막 요소를 새로 추가하려면 를 사용합니다.그거야, 동기화 같은 건 안 돼

ConcurentLinkedQueue는 매우 효율적인 대기/잠금 프리 구현(참조용 자바독 참조)이므로 동기화할 필요가 없을 뿐만 아니라 큐는 아무것도 잠그지 않으므로 동기화된(스레드 세이프가 아님) 큐와 거의 같은 속도가 됩니다.

비동시 컬렉션처럼 사용합니다.동시 [수집] 클래스는 액세스를 동기화할 필요가 없도록 일반 컬렉션을 래핑합니다.

편집: concurrent Linked List는 실제로는 단순한 래퍼가 아니라 보다 뛰어난 동시 구현입니다.어느 쪽이든 동기화에 대해 걱정할 필요가 없습니다.

언급URL : https://stackoverflow.com/questions/616484/how-to-use-concurrentlinkedqueue

반응형