问题:
在Java 代码中开了一个线程,死循环定时运行。
右键运行项目,再右键停目项目:
发现系统有提示警告:
警告: Web应用程序[ROOT]似乎启动了一个名为[Thread-1]的线程,但未能停止它。这很可能会造成内存泄漏。线程的堆栈跟踪:[ java.lang.Thread.sleep(Native Method) taurus.microservice.Run$1.run(Run.java:46) java.lang.Thread.run(Thread.java:745)] 九月 07, 2022 1:36:13 下午 org.apache.coyote.AbstractProtocol stop 信息: 正在停止ProtocolHandler ["http-nio-8090"] 九月 07, 2022 1:36:13 下午 org.apache.coyote.AbstractProtocol destroy 信息: 正在摧毁协议处理器 ["http-nio-8090"]
一开始,我以为线程已经停了,直到我开启了微服务,发现项目都停了,微服务还有不停的注册信息。
经过反复寻找,这才发现:
项目停止后,线程还在跑,而且开几次,就有几个线程在跑,What the fuck。
直到把整个Eclipse 退了,这些线程的运行才消息。
解决:
1、监听项目退出的信息。
package taurus.mvc.http; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; import taurus.mvc.tool.Debug; @WebListener() public class HttpServletContextListenerForJavax implements ServletContextListener { @Override public void contextDestroyed(ServletContextEvent arg0) { HttpContext.IsDestroyed=true; Debug.log("ServletContext Destroyed!"); } @Override public void contextInitialized(ServletContextEvent arg0) { // TODO Auto-generated method stub } }
退出时,把标识赋到一个全局变量中。
2、在线程里加上判断,如果项目退出,就退出线程的死循环。
new Thread(new Runnable() { public void run() { Random random=new Random(); Debug.log("MicroService.Run.start.Thread.Runnable : Start"); while (true) { try { if(HttpContext.IsDestroyed) { Debug.log("MicroService.Run.start.Thread.Runnable : Stoped"); break; } AfterRegHost(RegHost()); Thread.sleep(5000+random.nextInt(5000));//5-10秒循环1次。 } catch (Exception err) { Debug.log(err,"Run.start.Thread.Runnable"); try { Thread.sleep(5000+random.nextInt(5000));//5-10秒循环1次。 }catch (Exception e) {} } } } }).start();