title: Servlet "has started a thread but failed to stop it" - memory leak in Tomcat
body: <p>Apache Tomcat says many times:</p>
  
  <blockquote>
    <p>The web application [/MyServlet] appears to have started a thread named [pool-61-thread-2] but has failed to stop it. This is very likely to create a memory leak.</p>
  </blockquote>
  
  <p>Is this dangerous? The servlet should be able to handle 10.000requests/day.
  How to close the threads when they have finished?</p>
  
  <pre><code>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&lt;String[][]&gt; getSomeCallableStrArrArr(){
              return new Callable&lt;String[][]&gt;() {
                  public String[][] call() throws Exception {
                      return getSomeStrArrArr();
                  }
              };
          }
  
      }
  
      ExecutorService pool = Executors.newFixedThreadPool(3);
      Set&lt;Future&lt;String[][]&gt;&gt; set = new HashSet&lt;Future&lt;String[][]&gt;&gt;();
      CountDownLatch startSignal = new CountDownLatch(1);
      CountDownLatch doneSignal = new CountDownLatch(3);
      for (int i=1;i&lt;=3;i++) {
          Worker worker = new Worker(startSignal,doneSignal,i);
          Callable&lt;String[][]&gt; callable =
                  worker.getSomeCallableStrArrArr();
          Future&lt;String[][]&gt; future = pool.submit(callable);
          set.add(future);
      }
      startSignal.countDown();
      try {
          doneSignal.await();
  </code></pre>