2013-04-09 95 views
1

假设我有BlockingQueue,并且某些线程被称为take(),但此时队列为空。假设我以某种方式知道未来新元素不会出现在队列中。我如何释放那些被称为take()的线程等待?谢谢!BlockingQueue和释放等待中的线程

public void run() { 
     //noinspection InfiniteLoopStatement 
     while (true) { 
      try { 
       Thread.sleep(millisecondsToSleep); 
       if (!kitchen.processedOrdersEmpty()) { 
        Order processedOrder = kitchen.getFromProcessedOrders(); 
        kitchen.printMessage("took order#" + processedOrder.getOrderNumber()); 
        Thread.sleep(millisecondsToServe); 
        kitchen.printMessage("served order#" + processedOrder.getOrderNumber()); 
       } else { 
        int currentRandom = getNextRandom(); 
        if (currentRandom <= 10) { 
         Order newOrder = new Order(kitchen.getLastOrderNumber()); 
         kitchen.puIntoUnprocessedOrders(newOrder); 
         kitchen.printMessage("generated new order#" + newOrder.getOrderNumber()); 
        } else { 
         Thread.sleep(millisecondsToSleep); 
        } 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

其中kitchen.getFromProcessedOrders()等于:

public Order getFromProcessedOrders() throws InterruptedException { 
    return processedOrders.take(); 
} 

和processedOrders是BlockingQueue的

+0

你会告诉我们你的代码其中U已经产生的? – DRastislav 2013-04-09 09:56:52

+1

http://stackoverflow.com/questions/5378391/closing-a-blocking-queue – Edmondo1984 2013-04-09 09:58:42

+1

请稍等片刻:) – 2013-04-09 09:59:29

回答

2

根据java docs -

BlockingQueue不内在支持任何形式的“接近”或 “关机”操作指示没有更多的项目将被添加。需求和这些功能的使用倾向于取决于实现。例如,一种常见的策略是生产者插入特殊的 流结束或毒物,当消费者采取 时,相应地解释这些对象。

你应该中断的地方被阻塞线程 -

public void run() { 
        //noinspection InfiniteLoopStatement 
        while (true) { 
            try { 
                Thread.sleep(millisecondsToSleep); 
                if (!kitchen.processedOrdersEmpty()) { 
                    Order processedOrder = kitchen.getFromProcessedOrders(); 
                    kitchen.printMessage("took order#" + processedOrder.getOrderNumber()); 
                    Thread.sleep(millisecondsToServe); 
                    kitchen.printMessage("served order#" + processedOrder.getOrderNumber()); 
                } else { 
                    int currentRandom = getNextRandom(); 
                    if (currentRandom <= 10) { 
                        Order newOrder = new Order(kitchen.getLastOrderNumber()); 
                        kitchen.puIntoUnprocessedOrders(newOrder); 
                        kitchen.printMessage("generated new order#" + newOrder.getOrderNumber()); 
                    } else { 
                        Thread.sleep(millisecondsToSleep); 
                    } 
                } 
            } catch (InterruptedException ex) { 
       //... handle ... 
      }catch (Exception e) { 
                e.printStackTrace(); 
            } 
        } 
    } 
2

1)您可中断,其中取()正在运行

2线程)您可以将特殊对象放入队列中作为结束的信号。如果一个线程得到一个特殊的对象(END),它将它放回并退出,所以其他等待的线程也会得到END。

+0

3)设置一个volatile布尔值,指示线程应该退出。 – jontro 2013-04-09 10:18:14

+0

@jontro如果三个线程试图从一个大小为2的队列中取出,那不会有所帮助。第三个线程将无限期地等待 – 2013-04-09 10:51:37

+0

END的线程可以放回并退出 – 2013-04-09 11:01:40

0

您可以添加一些虚拟记录,如new String("##EOQ##")来表示队列结束并停止消费者线程。