简体   繁体   English

Java-在使用者正在等待并且tomcat关闭时停止线程

[英]Java - Stop thread while consumer is waiting and tomcat is shutdown

I have a servlet, and it is a singleton. 我有一个servlet,它是一个单例。

In the init, I create the producer and the consumers. 在初始化中,我创建了生产者和消费者。

consumer = new MyThread();
consumer.start();

and the method run is like this: 运行的方法是这样的:

@Override
public void run() {
    while (!isShutdown()) {
        if (queue.isEmpty())
            queue.wait();
        else
            ...
    }
}

then i have the destroy method. 然后我有销毁方法。 that set shutdown to true and I use .join 将shutdown设置为true,我使用.join

        consumer.setShutdown(true); 
        consumer.join();

but the method .join got lock.. and never finishes. 但是方法.join获得了锁定..并没有完成。 If I change the queue.wait to Thread.sleep(), it works... but I don't want to change... what I'm doing wrong? 如果我将queue.wait更改为Thread.sleep(),它可以工作...但是我不想更改...我做错了什么?

if I don't finish the thread, I got it: SEVERE: The web application [/test] appears to have started a thread named [Comsumer0] but has failed to stop it. 如果我没有完成线程,那么我得到了:严重:Web应用程序[/ test]似乎已经启动了一个名为[Comsumer0]的线程,但是未能停止它。 This is very likely to create a memory leak. 这很可能造成内存泄漏。

Most likely the queue is empty and since you have shutdown you never send anything into the queue to cause it to wake up. 队列很可能是空的,并且由于您已关闭,因此您绝不会将任何东西发送到队列中以使其醒来。

Fix this either by sending a dummy message to the queue after setting the shutdown flag or by just removing the shutdown flag completely and sending a shutdown command to the queue. 通过在设置关闭标志后向队列发送虚拟消息或仅完全删除关闭标志并向队列发送关闭命令来解决此问题。

Also be aware that if your shutdown flag is not volatile (or AtomicBoolean ) then one thread may not see it being set by the other due to caching inside the CPU. 还应注意,如果您的关闭标志不是volatile (或AtomicBoolean ),则由于CPU内部的缓存,一个线程可能看不到另一个线程正在设置它。

This is what the BlockingQueue is for: 这是BlockingQueue的用途:

    BlockingQueue queue = new ArrayBlockingQueue(5);
    // ...
    while (!isShutdown()) {
        Object poll = queue.poll(5, TimeUnit.SECONDS);
    }

you should change the design as advised above, or if you don't want to change your code, change your setShutdown() method body and statement to notify the queue. 您应该按照上面的建议更改设计,或者如果您不想更改代码,请更改setShutdown()方法主体和语句以通知队列。

public void setShutdown(boolean shutdown) {
  this.shutdown = shutdown;
  this.queue.notifyAll();
}

Using wait/notify methods is the old way to create a Consumer-Producer pattern. 使用等待/通知方法是创建使用者-生产者模式的旧方法。

It is better to use BlockingQueue. 最好使用BlockingQueue。

BlockingQueue.put() - for Producer, and BlockingQueue.poll() - for Consumer. BlockingQueue.put() -用于生产者,而BlockingQueue.poll() -用于消费者。

BlockingQueue hides wait method underneath BlockingQueue.poll , BlockingQueue.put and will block a Consumer thread until Producer adds value to queue. BlockingQueue将Waiting方法隐藏在BlockingQueue.pollBlockingQueue.put ,并将阻塞Consumer线程,直到Producer向队列添加值为止。

To fix the example above, you should make it wait for a finite amount of time like queue.wait(1000) , or wake consumer thread explicitly calling queue.notify() . 要修复上面的示例,您应该使它等待有限的时间,例如queue.wait(1000) ,或者唤醒显式调用queue.notify()使用者线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM