2011-08-15 10 views
2

Java에서 생산자/소비자 패턴을 구현하는 방법을 생각 중입니다.Java의 생산자/소비자 패턴

나는 3 개의 쓰레드와 하나의 태스크를 포함하는 List를 가지고 있다고 가정한다. 각 스레드는 목록에서 작업을 가져 와서 동시에 실행합니다. 나의 현재의 접근 방식은 내가 작업을 처리 할 때 스레드가 실패 할 경우,이 작업 목록에 다시 추가됩니다 현재 또는 다른 스레드에 의해 다시 포착 할 수 있다는 것입니다 달성하기 위해 원하는 것을 CountDownLatch를

int N = 3; 
CountDownLatch startSignal = new CountDownLatch(1); 
CountDownLatch doneSignal = new CountDownLatch(N); 
ConcurrentLinkedQueue<String> tasks = new ConcurrentLinkedQueue<String>(); 

main() { 
    for (int i=0;i<N;i++) { 
     new Thread(new Worker()).start(); 
    } 
    startSignal.countDown(); 
    doneSignal.await(); 
    System.out.println("done"); 
} 

class Worker implements Runnable { 
    public void run() { 
     startSignal.await(); 
      while ((s = tasks.poll()) != null) { 
       // do lengthy task here 
       if (task failed) { 
        tasks.add(s); 
        return; // assume that task fails badly and have to stop the thread 
       } 
      } 
     doneSignal.countDown(); 
    } 
} 

을 사용하는 것입니다 ,하지만 CountDownLatch를 사용하는 현재의 접근 방식에서는 doneSignal.countDown()이 호출 된 후에 스레드가 이미 작업을 완료 한 것으로 간주하므로 분명히 그렇게 할 수 없습니다.

이 시나리오에 가장 적합한 방법은 무엇입니까? Executor를 사용하는 것이 유일한 방법입니까?

답변

3

나는이 경우에 지나치게 복잡하고 (오류가 발생하기 쉬운) 해결책이라고 말하고 싶다. 일반적인 BlockingQueue를 사용하는 것이 더 간단 할 것이다. 하나의 스레드가이 차단 대기열에서 폴링하고 ExecutorService에 작업을 넘겨 준다. .

이 경우 CountDownLatch가 필요한 이유가 보이지 않습니다. 작업자를 불필요하게 복잡하게 만들고, 스레드 환경에서 실행 중이고 더러운 경우 정리해야한다는 것을 이해해야합니다. 끝내라. BlockingQueues 및 ExecutorServices는 이러한 문제에서 벗어나게 해줍니다.

+0

흠 .. 그래서 ExecutorService가 유일한 방법이라고 생각합니다. CountDownLatch를 사용하는 이유는 실제로 같은 것을 수행 할 계획입니다. while (완료되지 않음) {3 개의 스레드를 만들고 실행하십시오}'' 그래서 모든 스레드가 실제로 작업을 마치기 전에 작업을 완료하고 싶습니다. 다음 단계 – GantengX

+0

스레드가 작업을 수행하는 데 실패하면 ExecutorService가 다른 스레드로 작업을 전달할 수 있습니까? – GantengX

+0

Callable 's를 사용하여 Future 's를 얻고 응답을 기다리면 쉽게 시간 초과 할 수 있습니다. –