Servlet“has started a thread but failed to stop it”- Tomcat中的内存泄漏
Servlet“has started a thread but failed to stop it”- Tomcat中的内存泄漏
Apache Tomcat多次表示:
Web应用程序[/MyServlet]似乎已启动了一个名为[pool-61-thread-2]的线程,但未能停止它。这很可能会导致内存泄漏。
这是否危险?该servlet应该能够处理每天10,000个请求。
如何在线程完成后关闭它们?
class Worker { private final CountDownLatch startSignal; private final CountDownLatch doneSignal; private final int threadNumber; Worker( CountDownLatch startSignal, CountDownLatch doneSignal, int threadNumber ){ this.startSignal = startSignal; this.doneSignal = doneSignal; this.threadNumber = threadNumber; } public String[][] getSomeStrArrArr() { String[][] isRs = new String[8][20]; String[][] inRs = new String[8][20]; String[][] iwRs = new String[8][20]; try { startSignal.await(); if (threadNumber == 1) { // 获取线程1的String[][]结果 isRs = getIS(erg1, erg2, request); } if (threadNumber == 2) { // 获取线程2的String[][]结果 inRs = getIN(search_plz, request); } if (threadNumber == 3) { // 获取线程3的String[][]结果 iwRs = getIW(erg1, erg2, request); } doneSignal.countDown(); } catch (InterruptedException ex) { System.out.println( "线程"+threadNumber+"已被中断。" ); } if (threadNumber == 1) { return isRs; } if (threadNumber == 2) { return inRs; } if (threadNumber == 3) { return iwRs; } return null; } public CallablegetSomeCallableStrArrArr(){ return new Callable () { public String[][] call() throws Exception { return getSomeStrArrArr(); } }; } } ExecutorService pool = Executors.newFixedThreadPool(3); Set > set = new HashSet >(); CountDownLatch startSignal = new CountDownLatch(1); CountDownLatch doneSignal = new CountDownLatch(3); for (int i=1;i<=3;i++) { Worker worker = new Worker(startSignal,doneSignal,i); Callable callable = worker.getSomeCallableStrArrArr(); Future future = pool.submit(callable); set.add(future); } startSignal.countDown(); try { doneSignal.await();
Servlet "has started a thread but failed to stop it" - memory leak in Tomcat问题的出现的原因是,当代码启动非守护线程时,这些线程会继续工作直到它们退出run方法。即使其他所有操作都完成,旧的JVM仍会保持活动状态,而这些线程继续执行。如果启动一个新的实例,就会出现旧线程与新实例创建的线程并行工作的情况。
解决方法是,任务需要设计成对中断响应(而不是吃掉异常并继续执行,这是你的示例所展示的)。这意味着在当前线程上检查中断标志,并以有帮助的方式捕获InterruptedException,使任务能够中断工作并在需要时重置中断标志。ExecutorService实现提供了一个shutdownNow方法,可以中断当前任务。
确保执行器被关闭,可以在ServletContextListener中处理。
如果线程是通过callable创建的而不是runnable,因为需要从每个线程中返回,是否也适用于中断?我需要返回结果并且不知道线程什么时候返回...
你的示例代码不完整,你是否在关闭线程池时做了任何操作?
ExecutorService.shutdownNow。如果任务能够对中断做出响应会更有帮助。
简单但有效!我希望它有效,我不再遇到任何错误了。谢谢!你对这个问题有了解吗:"The web application [/MyServlet] appears to have started a thread named [MySQL Statement Cancellation Timer] but has failed to stop it. This is very likely to create a memory leak." 我只是进行一些普通的mysql调用,没有特殊的操作...
感谢Nathan,我使用的是旧的5.0.8 mysql连接器。更新到最新版本后问题/错误解决了!
我由于quartz worker而出现了内存泄漏。如何停止JVM中的所有连接和quartz线程。我在以下URL中遇到了问题:stackoverflow.com/questions/39166512/…