如何编写生产就绪的单一消费者?

时间:2013-01-23 21:36:06

标签: java concurrency producer-consumer

以下是阻塞队列的单个使用者的简单实现。我的问题是,我应该使用哪些附加代码使其生产就绪?假设我需要这个消费者永远存在。

一些问题,例如:

  1. 是否(真的)足够好?
  2. 当我收到InterruptedException以便我可以尝试恢复我正在做的事情时该怎么办?
  3. 如果线程挂起会发生什么?
  4. 如果线程因异常而终止会怎样?
  5. 我想我的整体问题是关于实现这个单线程消费者的管理和监控的一些想法。或者是否存在提供基本实现的现有库。

    非常感谢!

    public class Consumer implements Runnable{
    
        private BlockingQueue queue;
    
        public Consumer (BlockingQueue queue) {
            this.queue = queue;
        }
    
        @Override
        public void run() {
            while(true){
                try {
                    Object task = queue.take();
                    ...
                } catch (InterruptedException ex) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
    

2 个答案:

答案 0 :(得分:4)

  

while(true)是否足够好?

糟糕。 @Cratylus强调你应该总是使用:

 while (!Thread.currentThread().isInterrupted()) {

你需要在抓住异常时保持宗教信仰 - 甚至可能抓住RuntimeException甚至Throwable。至少你应该考虑在退出之前捕获并记录消息。

  

当我收到InterruptedException以便我可以尝试恢复我正在做的事情时该怎么办?

这取决于你希望线程做什么。 IMO,当线程被中断时,它应该被(呃)中断。由于thread.stop()由于多种原因而被弃用,thread.interrupt()确实是阻止线程运行的唯一方法。这意味着它应该清理并退出。

} catch (InterruptedException ex) {
    // always a good practice to re-interrupt
    Thread.currentThread().interrupt();
    // but now what to do?  I vote for stopping the thread
    return;
}
  

如果线程挂起会发生什么?

除非你的程序中有bug,否则永远不会发生这种情况。它可能会在queue.take()上永远等待,但是中断应该将它踢出去。

小心多个synchronized部分以防止死锁。请务必使用java.util.concurrent.*类(BlockingQueueExecutors,...)来解释用户代码导致问题的可能性。使用Atomic*类。线程之间共享的所有数据都需要正确synchronizedvolatile

  

如果线程因异常而终止会怎样?

你想要发生什么?你应该(再次)虔诚地捕捉异常,如果那是你想做的事情。如果你希望线程在看到异常时停止,那么我将捕获异常,记录它,然后清理并返回。异常处理没有简单的答案。

答案 1 :(得分:3)

  

虽然(真)足够好吗?

没有。你应该while(!interrupted)

  

当我收到InterruptedException以便我可以尝试时该怎么办   恢复我在做什么?

如果您遇到中断的异常,则不应该恢复。这是一个停止的信号

  

如果线程挂起会发生什么?

如果您在中断时退出,则不会。它将以您当前的形式挂起(没有办法阻止它,因为您当前编码它)

  

如果线程因异常而终止会怎样?

终止。不确定你的意思。