/**
* Should Tomcat attempt to terminate threads that have been started by the
* web application? Stopping threads is performed via the deprecated (for
* good reason) <code>Thread.stop()</code> method and is likely to result in
* instability. As such, enabling this should be viewed as an option of last
* resort in a development environment and is not recommended in a
* production environment. If not specified, the default value of
* <code>false</code> will be used.
*/
private boolean clearReferencesStopThreads = false;
我猜weblogic也是类似的策略,所以不能指望应用服务器给你清理线程。
应该在什么地方清理线程?
正确的停止应用线程的方法是自己去停止,而不要依赖于应用服务器!
例如,使用spring的,可以利用bean的destroy方法,或者没有spring的,注册一个listener。
public class ContextDestroyListener
implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
// TODO Auto-generated method stub
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// TODO Auto-generated method stub
//在这个地方清理线程
}
}
我们知道在什么地方去清理这些线程了,接下来就是如何去清理他们了。清理线程并不是加个shutdown方法或者调用一下interrupt那么简单的事情。
如何正确停止线程?
要自己停止线程,首先你得拿到线程的句柄,也就是thread对象或者线程池,如果你写了下面的代码,启动完后你就找不到这个线程了,所以线程一定要在清理线程的时候能拿得到句柄。
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
try {
Thread.sleep(1000);
System.out.println("wake up");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
正确的方法是把Thread放到一个变量里,例如t,然后通过t去停止这个线程。停止线程的方法一般有stop,destroy,interrupt等,但是stop,destroy都已经被废弃了,因为可能造成死锁,所以通常等做法是使用interrupt。使用interrupt其实类似于信号,就好比你在Linux进程中把SIGTERM信号忽略了,那就没法通过kill杀死进程了,interrupt也是如此。 下面等线程只会报一个异常,中断信号被忽略。
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while(true) {
try {
Thread.sleep(1000);
System.out.println("wake up");
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
});
t.start();
t.interrupt();//并不能停止线程
}