BlockingQueue并从等待中释放线程

时间:2013-04-09 09:54:53

标签: java multithreading collections blockingqueue

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

  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

3 个答案:

答案 0 :(得分:2)

1)您可以中断运行take()的线程

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

答案 1 :(得分: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 :(得分:0)

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