Servlet“已启动一个线程但未能阻止它” – 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) { // get String[][] result for thread number 1 isRs = getIS(erg1, erg2, request); } if (threadNumber == 2) { // get String[][] result for thread number 2 inRs = getIN(search_plz, request); } if (threadNumber == 3) { // get String[][] result for thread number 3 iwRs = getIW(erg1, erg2, request); } doneSignal.countDown(); } catch (InterruptedException ex) { System.out.println( "Thread number "+threadNumber+" has been interrupted." ); } if (threadNumber == 1) { return isRs; } if (threadNumber == 2) { return inRs; } if (threadNumber == 3) { return iwRs; } return null; } public Callable getSomeCallableStrArrArr(){ return new Callable() { public String[][] call() throws Exception { return getSomeStrArrArr(); } }; } } ExecutorService pool = Executors.newFixedThreadPool(3); Set<Future> set = new HashSet<Future>(); 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(); 

是的,这是一个问题。 如果您的代码启动非守护程序线程,那么这些线程将继续工作,直到它们退出其run方法。 即使其他一切都完成了,旧的JVM也会在这些线程继续运行的时候徘徊。 如果启动一个新实例,那么您可能会遇到旧线程仍然与新实例创建的线程一起工作的情况。

需要设计任务,以便他们能够响应中断(而不是吃exception并继续进行,这就是你的例子所示)。 这意味着检查当前线程上的中断标志,并以一种有用的方式捕获InterruptedException,允许任务中断其工作,并在需要时重置中断的标志。 ExecutorService实现有一个shutdownNow方法,它将中断当前任务。

这是一个如何使用中断停止线程的示例 。

确保执行程序关闭, 您可以在ServletContextListener中处理它 。