Servlet“has started a thread but failed to stop it”- Tomcat中的内存泄漏

10 浏览
0 Comments

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 Callable getSomeCallableStrArrArr(){
            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();

0
0 Comments

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/…

0