title: Java ExecutorService - Task/Callable not cancelling/interrupting
body: <p>I am using Java ExecutorService (ThreadPool) to perform a task &amp; update UI while a particular activity is in foreground (visible).</p>
  
  <p><strong>Problem:</strong>
  What i want is when user switches to another activity i want to stop/cancel all the task(whether queued or running). And for this i have to either use ExecutorService shutdown/shutdownNow method or cancel(true) on Future object returned by ExecutorService submit method after checking of Future object status by calling isDone(). This would set the corresponding thread flag for interruption to TRUE which i have to check (Thread.currentThread.isInterrupted()) in my callable implementation to determine if is interrupted exit the task/thread. Problem is whether i call ExecutorService shutdown method or Future cancel(true) method in both the cases rarely 1 of 10 times it sets the thread interruption flag to TRUE which is eventually leading to memory leaks, etc.</p>
  
  <p><strong>Code:</strong></p>
  
  <p>ThreadPool Singleton implementation(cancelAll-to cancel tasks &amp; shutdownExecutor-to shutdown ExecutorService):</p>
  
  <pre><code>private static class ThreadPoolManager {
  
      private ExecutorService executorService;
      private List&lt;Future&gt; queuedFutures;
      private BlockingQueue&lt;Runnable&gt; blockingQueue;
  
      private static ThreadPoolManager instance;
  
      private ThreadPoolManager() {
          MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Threadpool-created(constructor)");
          queuedFutures = new ArrayList&lt;&gt;();
          blockingQueue = new LinkedBlockingDeque&lt;&gt;();
          executorService = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), Runtime.getRuntime().availableProcessors(), 1, TimeUnit.SECONDS, blockingQueue);
      }
  
      static {
          instance = new ThreadPoolManager();
      }
  
      public static void submitItemTest(Callable&lt;Object&gt; callable) {
          MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Threadpool-submitted item test");
          if(instance.executorService.isShutdown()){
              instance=new ThreadPoolManager();
          }
          Future future = instance.executorService.submit(callable);
          instance.queuedFutures.add(future);
      }
  
      public static void submitTestAll(Callable&lt;Object&gt; callable) {
          MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Threadpool-submitted test all");
          if(instance.executorService.isShutdown()){
              instance=new ThreadPoolManager();
          }
          cancelAll();
          Future future = instance.executorService.submit(callable);
          instance.queuedFutures.add(future);
      }
  
      public static void cancelAll() {
          MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Cancelling all future tasks");
          instance.blockingQueue.clear();
          for (Future future : instance.queuedFutures) {
              if (!future.isDone()) {
                  boolean cancelled = future.cancel(true);
                  MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Cancelled-" + cancelled);
              }
          }
          instance.queuedFutures.clear();
      }
  
      public static void shutdownExecutor(){
          MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Shuttingdown threadpool");
          instance.executorService.shutdownNow();
      }
  }
  </code></pre>
  
  <p>Callable Implementation(normal iteration &amp; if clause to check for interruption):</p>
  
  <pre><code>private Callable&lt;Object&gt; getTestAllCallable() {
          return new Callable&lt;Object&gt;() {
              @Override
              public Object call() {
                  for (int i = 0; i &lt; inbuiltProxyPojoArrayList.size(); i++) {
                      if (!Thread.currentThread().isInterrupted()) {
                            //someWork
  
                      } else {
                          MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "ThreadInterrupted-Cancelling");
                          return null;
                      }
                  }
                  return null;
              }
          };
      }
  </code></pre>
  
  <p>Activity/Fragment onStop implementation(for invoking cancel task &amp; shutdown):</p>
  
  <pre><code>@Override
  public void onStop() {
      MyLogger.log(MyLogger.LOG_TYPE.INFO, "onStop called");
      ThreadPoolManager.cancelAll();
      ThreadPoolManager.shutdownExecutor();
      super.onStop();
  }
  </code></pre>
  
  <p><strong>Update:</strong></p>
  
  <p>Changes made:</p>
  
  <ol>
  <li><p>Moved from using Runnable instead of callable.</p></li>
  <li><p>Now not using singleton for ExecutorService.</p>
  
  <pre><code>  private class ThreadPoolManager {
  
      private ExecutorService executorService;
      private List&lt;Future&gt; queuedFutures;
      private BlockingQueue&lt;Runnable&gt; blockingQueue;
  
      private ThreadPoolManager() {
          MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Threadpool-created(constructor)");
          queuedFutures = new ArrayList&lt;&gt;();
          blockingQueue = new LinkedBlockingDeque&lt;&gt;();
          executorService =getNewExecutorService();
      }
  
      private ExecutorService getNewExecutorService(){
          return new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), Runtime.getRuntime().availableProcessors(), 1, TimeUnit.SECONDS, blockingQueue);
      }
  
      private void submitItemTest(Runnable runnable) {
          MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Threadpool-submitted item test");
          if(executorService.isShutdown()){
              executorService=getNewExecutorService();
          }
          Future future = executorService.submit(runnable);
          queuedFutures.add(future);
      }
  
      private void submitTestAll(Runnable runnable) {
          MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Threadpool-submitted test all");
          if(executorService.isShutdown()){
              executorService=getNewExecutorService();
          }
          cancelAll();
          Future future = executorService.submit(runnable);
          queuedFutures.add(future);
      }
  
      private void cancelAll() {
          MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Cancelling all future tasks");
          blockingQueue.clear();
          for (Future future : queuedFutures) {
              if (!future.isDone()) {
                  boolean cancelled = future.cancel(true);
                  MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Cancelled-" + cancelled);
              }
          }
          queuedFutures.clear();
      }
  
      private void shutdownExecutor(){
          MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Shuttingdown threadpool");
          executorService.shutdownNow();
          blockingQueue.clear();
          queuedFutures.clear();
      }
  }
  </code></pre></li>
  </ol>
  
  <p>Found out the culprit but not the solution yet. Following 2 are the implementation of Runnables 1 of which is working (isInterrupted returns true or comes InterupptedException and than task ended) but not other.</p>
  
  <p>Working Runnable(I used it for testing):</p>
  
  <pre><code>new Runnable() {
            @Override
            public void run() {
                      int i=0;
                      while(!Thread.currentThread().isInterrupted()){
                          try {
                              System.out.println(i);
                              Thread.currentThread().sleep(2000);
                          } catch (InterruptedException e) {
                              MyLogger.log(MyLogger.LOG_TYPE.DEBUG,"Interrupted");
                              return;
                          }
                          i++;
                      }
                  }
              }
  </code></pre>
  
  <p>Not working(actual code i want to use):</p>
  
  <pre><code>new Runnable(){
              @Override
              public void run() {
                  for (int i = 0; i &lt; inbuiltProxyPojoArrayList.size(); i++) {
                      if (!Thread.currentThread().isInterrupted()) {
  
                      } else {
                          MyLogger.log(MyLogger.LOG_TYPE.DEBUG, "Thread Interrupted (Cancelled)");
                          break;
                      }
                  }
              }
          };
  </code></pre>
  
  <p>And 1 probable solution would be to use variable(boolean) as a interruption flag inside the runnable that i will consider as a last resort but would happy to get to know the mistake.</p>