Java - 在消费者等待并且tomcat关闭时停止线程

时间:2015-12-08 16:03:52

标签: java multithreading tomcat thread-safety

我有一个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]但未能阻止它的线程。这很可能会造成内存泄漏。

4 个答案:

答案 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)