我有一个servlet,它是一个单例。
在init中,我创建了生产者和消费者。
consumer = new MyThread();
consumer.start();
并且运行方法如下:
@Override
public void run() {
while (!isShutdown()) {
if (queue.isEmpty())
queue.wait();
else
...
}
}
然后我有了destroy方法。 将shutdown设置为true并使用.join
consumer.setShutdown(true);
consumer.join();
但是方法.join得到了锁定......并且永远不会完成。 如果我将queue.wait更改为Thread.sleep(),它可以工作......但我不想改变......我做错了什么?
如果我没有完成线程,我得到了它: 严重:Web应用程序[/ test]似乎已经启动了一个名为[Comsumer0]但未能阻止它的线程。这很可能会造成内存泄漏。
答案 0 :(得分:0)
队列很可能是空的,因为你已经关闭了,所以你永远不会向队列发送任何东西以使其被唤醒。
通过在设置关闭标志后向队列发送虚假消息,或者只是完全删除关闭标志并向队列发送shutdown命令来解决此问题。
另请注意,如果关闭标志不是volatile
(或AtomicBoolean
),则由于CPU内部的缓存,一个线程可能看不到另一个线程被另一个线程设置。
答案 1 :(得分:0)
这是BlockingQueue的用途:
BlockingQueue queue = new ArrayBlockingQueue(5);
// ...
while (!isShutdown()) {
Object poll = queue.poll(5, TimeUnit.SECONDS);
}
答案 2 :(得分:0)
您应该按照上面的建议更改设计,或者如果您不想更改代码,请更改setShutdown()方法主体和语句以通知队列。
public void setShutdown(boolean shutdown) {
this.shutdown = shutdown;
this.queue.notifyAll();
}
答案 3 :(得分:0)
使用wait / notify方法是创建Consumer-Producer模式的旧方法。
最好使用BlockingQueue。
if(isset($row['name']) && isset($row['price'])) {
//echo your results
} else {
//return an error
}
- 适用于制作人,BlockingQueue.put()
- 适用于消费者。
BlockingQueue隐藏BlockingQueue.poll()
,BlockingQueue.poll
下面的wait方法,并阻止Consumer线程直到Producer为队列添加值。
要修复上面的示例,您应该让它等待有限的时间,如BlockingQueue.put
,或者唤醒消费者线程,显式调用queue.wait(1000)
。