2009-08-27 4 views
3

고정 용량의 Java 목록이 필요하지만 항상 스레드가 항목을 시작 부분에 추가 할 수 있습니다. 가득 차 있다면 공간을 확보하기 위해 끝에서 항목을 제거해야합니다. 다른 프로세스는 항목을 제거하지 않지만 다른 프로세스는 항목을 반복하려고합니다.Java 대기열/목록에 대한 원자 적으로 "여유 공간 또는 대기열에서 대기열에 넣은 다음 대기열에 넣을 경우 대기열에 넣을 수 있습니까?"

JDK에는 이걸 내가 원자 적으로 할 수있는 것이 있습니까?

현재 나의 계획은 기존의 threadsafe Collection (예 : LinkedBlockingQueue)을 사용하고 용량/추가/제거를 확인할 때 동기화됩니다. 그게 효과가 있니?

감사합니다.

+0

JDK에서 다루지 않는 흥미로운 사용 사례. – starblue

답변

0

이전 버전의 Java (예 1.3, 선택의 여지가 없습니다)에서 작업하고 있으므로 나중에 Javas에 있어도 사용할 수 없습니다. 그래서 나는이 라인을 따라 코딩 :

public class Fifo { 
private LinkedList fifoContents = new LinkedList(); 
public synchronized void put(Object element) { 
    if (fifoContents.size() > 100){    
      fifoContents.removeFirst();     
      logger.logWarning("*** Backlog, discarding messaage "); 
    } 
    fifoContents.add (element); 
    return; 
} 

public synchronized Object get() throws NoSuchElementException { 
    return fifoContents.removeFirst(); 
} 
} 
1

당신의 생각은 (아래 예 참조) 일 것이다하지만 여러 잠금을 복용 포함한다. 데이터를 추가 할 때 여러 작업을 동기화해야 할 경우 QueueLinkedList 구현을 에 랩핑하면 추가 잠금 오버 헤드를 피할 수 있습니다.

// Create queue with fixed capacity. 
Queue<Item> queue = new LinkedBlockingQueue<Item>(1000); 

... 

// Attempt to add item to queue, removing items if required. 
synchronized(queue) { // First lock 
    while (!queue.offer(item)) { // Second lock 
    queue.take(); // Third lock 
    } 
} 
0

당신은 단지에 추가 잠금없이 삽입/제거/테스트와 멀리 얻을 수 있습니다 :

class DroppingQueue<E> 
extends ArrayBlockingQueue<E> { 
    public boolean add(E item) { 
     while (! offer(item)) { 
      take(); 
     } 
     return true; 
    } 
} 

이 방법은 동기화되지 않지만, addoffer은 여전히, 그래서 최악의 그 수 스레드 1 번이 offer으로 전화를 걸면 전체 대기열을 찾으며 2 번 스레드는 동일하게 처리하고 두 스레드가 성공적으로 항목을 추가하기 전에 둘 다 항목의 수를 일시적으로 최대 값보다 더 줄이는 항목을 제거합니다. . 아마도 심각한 문제는 발생하지 않을 것입니다.

+1

이 솔루션에서 발생할 수있는 최악의 상황은 스레드 # 1이 항목을 가져올 때마다 스레드 # 1이 진행되기 전에 다른 스레드가 다른 항목을 제공한다는 것입니다. 그러나 이것은 시나리오보다 가능성이 적습니다. –

0

JDK에는 이러한 클래스가 없습니다. 이러한 콜렉션을 구현하려는 경우 고정 된 머리글/꼬리 포인터가있는 배열을 사용하는 것이 좋습니다. 링크 된 목록이 전혀 필요하지 않은 고정 된 크기이기 때문입니다.

관련 문제