簡體   English   中英

Servlet“已啟動一個線程但未能阻止它” - Tomcat中的內存泄漏

[英]Servlet “has started a thread but failed to stop it” - memory leak in 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<String[][]> getSomeCallableStrArrArr(){
            return new Callable<String[][]>() {
                public String[][] call() throws Exception {
                    return getSomeStrArrArr();
                }
            };
        }

    }

    ExecutorService pool = Executors.newFixedThreadPool(3);
    Set<Future<String[][]>> set = new HashSet<Future<String[][]>>();
    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<String[][]> callable =
                worker.getSomeCallableStrArrArr();
        Future<String[][]> future = pool.submit(callable);
        set.add(future);
    }
    startSignal.countDown();
    try {
        doneSignal.await();

是的,這是一個問題。 如果您的代碼啟動非守護程序線程,那么這些線程將繼續工作,直到它們退出其run方法。 即使其他一切都完成了,舊的JVM也會在這些線程繼續運行的時候徘徊。 如果啟動一個新實例,那么您可能會遇到舊線程仍在與新實例創建的線程一起工作的情況。

需要設計任務,以便他們能夠響應中斷(而不是吃異常並繼續進行,這就是你的例子所示)。 這意味着檢查當前線程上的中斷標志,並以有用的方式捕獲InterruptedException,允許任務中斷其工作,並在需要時重置中斷的標志。 ExecutorService實現有一個shutdownNow方法,它將中斷當前任務。

這是一個如何使用中斷停止線程的示例

確保執行程序關閉, 您可以在ServletContextListener中處理它

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM