2014-01-26 26 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); 
     } 
    } 
} 

任何人都可以解釋爲什麼消費者線程不起作用的第一種情況?

對於第一種情況,在eclipse中,我可以看到消費者線程並未死亡。我暫停它,它正在研究這一行現在

 if(!queue.isEmpty()) { 

如果我手動步驟結束後,消費者將工作和打印日誌。但是,只要我恢復並讓它自行運行,它就會再次卡住。

我想了解更多的Java。

謝謝!

-Erben

+1

你應該使用某種'BlockingQueue'。 –

+0

你沒有顯示任何有關代碼的另一面,但我懷疑你沒有使用適當的線程安全隊列實現。 – chrylis

+0

也許您的消費者任務已經終止(例如由於併發修改異常),如果發生這種情況,您將看不到任何異常,因爲執行者會返回給您未來的結果或異常,而不會產生嘈雜的崩潰。 – zapl

回答

4

在這種情況下有多個問題。

  1. 您的第一個實現運行一個緊密的循環。根據平臺和線程模型的不同,它可能不允許任何其他線程運行。這就是生產者線程沒有機會將數據放入隊列的原因。
  2. 您的第二個實現(使用Thread.sleep)爲其他線程運行提供了機會。這就是爲什麼你看到消費者消費某些東西的原因,因爲生產者線程有機會將數據放入隊列中。但是,即使這個問題也是因爲你沒有同步生產者和消費者而面臨失敗。學習線程同步請參見Java Tutorial - Synchronization