2014-01-26 2 views
0

저는 Java를 배우며 기본 생산자 - 소비자 용례를 구현하고 있습니다. 대기열과 일부 대기열에 물건을 넣는 생산자가 있습니다. 또한 Callable을 구현하는 Consumer가 하나 있습니다.java while (true) 대기열을 폴링하여 실행하지 않음

public String call() throws Exception 
{ 
    while(true) { 
     if(!queue.isEmpty()) { 
      String prod = queue.poll(); 
      System.out.println(name + " consumed " + prod); 
     } 
    } 
} 

프로듀서 :

@Override 
public void run() { 
    System.out.println("adding " + name); 
    queue.add(name); 
} 

홈페이지 : 여기에 소비자의 구현은

public static void main(String[] args) { 
    Test(); 
} 

public static void Test() 
{ 
    Queue<String> queue = new LinkedList<String>(); 

    ScheduledExecutorService lots_of_producers = Executors.newScheduledThreadPool(10); 
    ExecutorService consumers = Executors.newFixedThreadPool(1); 


    for(int i=0; i<1; i++) { 
     Consumer consumer = new Consumer("consumer_" + i, queue); 
     consumers.submit(consumer); 
    } 

    for(int i=0; i<5; i++) { 
     Producer producer = new Producer("producer_" + i, queue); 
     lots_of_producers.scheduleWithFixedDelay(producer, i, 5, TimeUnit.SECONDS); 
    } 
} 

생산자가 잘 작동하지만 소비자의 로그를 참조하지 않았기 때문에 소비자가 작동하지 않습니다 .

그러나 소비 구현을 변경하고 queue.isEmpty()가 true 일 때 소비자 스레드가 잠자기 상태가되면 소비자는 예상대로 작동합니다.

public String call() throws Exception 
{ 
    while(true) { 
     if(!queue.isEmpty()) { 
      String prod = queue.poll(); 
      System.out.println(name + " consumed " + prod); 
     } else { 
      Thread.sleep(100); 
     } 
    } 
} 

왜 소비자 스레드가 첫 번째 경우에 작동하지 않는지 설명 할 수 있습니까?

또한 첫 번째 경우에 일식에서 소비자 스레드가 죽지 않았 음을 알 수 있습니다. 일시 중지하고이 줄에서 작업하고 있습니다.

 if(!queue.isEmpty()) { 

이제 수동으로 단계를 넘기면 소비자가 작업하고 로그를 인쇄합니다. 그러나 내가 다시 시작하고 그것이 스스로 실행되도록하자마자, 다시 붙어있을 것이다.

자바를 더 잘 이해하려고합니다.

감사합니다.

-erben

+1

'BlockingQueue'를 사용해야합니다. –

+0

코드의 다른쪽에 대해서는 아무 것도 표시하지 않았지만 적절한 스레드 안전 큐 구현을 사용하고 있지 않은 것 같습니다. – chrylis

+0

예를 들어 동시 수정 예외로 인해 소비자 작업이 중단 된 경우 집행 담당자가 시끄러운 충돌을 생성하는 대신 결과 나 예외를 반환하는 미래를 반환하기 때문에 예외가 표시되지 않습니다. – zapl

답변

4

이 경우 여러 가지 문제가 있습니다.

  1. 첫 번째 구현은 엄격한 루프를 실행합니다. 플랫폼 및 스레딩 모델에 따라 다른 스레드가 전혀 실행되지 않을 수도 있습니다. 이것이 제작자 스레드가 데이터를 대기열에 넣을 기회를 얻지 못하는 이유입니다.
  2. 두 번째 구현 (Thread.sleep)은 다른 스레드가 실행될 수있는 기회를 제공합니다. 이것이 제작자 스레드가 데이터를 대기열에 넣을 기회를 얻으므로 소비자가 무언가를 소비하는 것을 보는 이유입니다. 그러나 제작자와 소비자를 동기화하지 않았으므로이 파일도 열려 있습니다. 스레드 동기화를 배우려면 Java Tutorial - Synchronization을 참조하십시오.