假设我有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
答案 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##")
,以表示队列结束并停止使用者线程。