2014-01-26 27 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