title: future.isDone returns false even if the task is done
body: <p>I have tricky situation, Does <code>future.isDone()</code> returns <code>false</code>, even if the thread is done.</p>
  
  <pre><code>import java.util.ArrayList;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.concurrent.ArrayBlockingQueue;
  import java.util.concurrent.Callable;
  import java.util.concurrent.CountDownLatch;
  import java.util.concurrent.ExecutionException;
  import java.util.concurrent.Future;
  import java.util.concurrent.ThreadPoolExecutor;
  import java.util.concurrent.TimeUnit;
  
  public class DataAccessor {
      private static ThreadPoolExecutor executor;
      private int timeout = 100000;
      static {
          executor = new ThreadPoolExecutor(10, 10, 1000, TimeUnit.SECONDS, new ArrayBlockingQueue&lt;Runnable&gt;(1000));
      }
  
      public static void main(String[] args) {
          List&lt;String&gt; requests = new ArrayList&lt;String&gt;();
          for(int i=0; i&lt;20; i++){
              requests.add("request:"+i);
          }
          DataAccessor dataAccessor = new DataAccessor();
  
          List&lt;ProcessedResponse&gt; results = dataAccessor.getDataFromService(requests);
          for(ProcessedResponse response:results){
              System.out.println("response"+response.toString()+"\n");
          }
          executor.shutdown();
      }
  
      public List&lt;ProcessedResponse&gt; getDataFromService(List&lt;String&gt; requests) {
          final CountDownLatch latch = new CountDownLatch(requests.size());
          List&lt;SubmittedJob&gt; submittedJobs = new ArrayList&lt;SubmittedJob&gt;(requests.size());
          for (String request : requests) {
              Future&lt;ProcessedResponse&gt; future = executor.submit(new GetAndProcessResponse(request, latch));
              submittedJobs.add(new SubmittedJob(future, request));
          }
          try {
              if (!latch.await(timeout, TimeUnit.MILLISECONDS)) {
                  // some of the jobs not done
                  System.out.println("some jobs not done");
              }
          } catch (InterruptedException e1) {
              // take care, or cleanup
              for (SubmittedJob job : submittedJobs) {
                  job.getFuture().cancel(true);
              }
          }
          List&lt;ProcessedResponse&gt; results = new LinkedList&lt;DataAccessor.ProcessedResponse&gt;();
          for (SubmittedJob job : submittedJobs) {
              try {
                  // before doing a get you may check if it is done
                  if (!job.getFuture().isDone()) {
                      // cancel job and continue with others
                      job.getFuture().cancel(true);
                      continue;
                  }
                  ProcessedResponse response = job.getFuture().get();
                  results.add(response);
              } catch (ExecutionException cause) {
                  // exceptions occurred during execution, in any
              } catch (InterruptedException e) {
                  // take care
              }
          }
          return results;
      }
  
      private class SubmittedJob {
          final String request;
          final Future&lt;ProcessedResponse&gt; future;
  
          public Future&lt;ProcessedResponse&gt; getFuture() {
              return future;
          }
  
          public String getRequest() {
              return request;
          }
  
          SubmittedJob(final Future&lt;ProcessedResponse&gt; job, final String request) {
              this.future = job;
              this.request = request;
          }
      }
  
      private class ProcessedResponse {
          private final String request;
          private final String response;
  
          ProcessedResponse(final String request, final String response) {
              this.request = request;
              this.response = response;
          }
  
          public String getRequest() {
              return request;
          }
  
          public String getResponse() {
              return response;
          }
  
          public String toString(){
              return "[request:"+request+","+"response:"+ response+"]";
          }
      }
  
      private class GetAndProcessResponse implements Callable&lt;ProcessedResponse&gt; {
          private final String request;
          private final CountDownLatch countDownLatch;
  
          GetAndProcessResponse(final String request, final CountDownLatch countDownLatch) {
              this.request = request;
              this.countDownLatch = countDownLatch;
          }
  
          public ProcessedResponse call() {
              try {
                  return getAndProcessResponse(this.request);
              } finally {
                  countDownLatch.countDown();
              }
          }
  
          private ProcessedResponse getAndProcessResponse(final String request) {
              // do the service call
              // ........
              if("request:16".equals(request)){
                  throw (new RuntimeException("runtime"));
              }
              return (new ProcessedResponse(request, "response.of." + request));
          }
      }
  }
  </code></pre>
  
  <p>if  I call <code>future.isDone()</code> it returns <code>false</code> though the <code>coundownLatch.await()</code> return true. Any Idea? Also to note that the countDownLatch.await comes out immediately when this happens.</p>
  
  <p>If you are finding the format not readable view here, <a href="http://tinyurl.com/7j6cvep" rel="noreferrer">http://tinyurl.com/7j6cvep</a> .</p>