Future cancel method documentation

2019-05-14 09:25发布

问题:

According to http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html isDone returns true if cancel(boolean mayInterruptIfRunning) was called.

After this method returns, subsequent calls to isDone() will always return true.

However, it is possible that task is running and mayInterruptIfRunning is set to false. So, what should return isDone() right after that call? true because of cancel (which is wrong)?

Also, it's not clear whether cancel(boolean) method returns false.

P. S. I'm implementing some simple thread pool, so I'm inheriting from Future.

回答1:

  1. After cancel(...), isDone() should always be true. It doesn't matter what cancel(...) returned.
  2. If cancel(...) returns true it means this future is now cancelled and isCancelled()==true
  3. If cancel(...) returns false it means that the completion was not due to this call to cancel()
  4. cancel(false) means that the cancel method should not attempt to cancel the task that is trying to complete the future (the meaning of "task" depending on the Future's implementation), the task will keep running but the future is cancelled (isDone()==true).
  5. cancel(true) means that there should be an attempt to cancel the running task, regardless if the attempt is successful or not the future will be cancelled (isDone()==true).

Remember that this is a contract, it has to be enforced by the Future's implementation.

Edit: isDone() is always true after cancel()

Here's a test to experiment with some of the scenarios:

@Test
public void test() throws ExecutionException, InterruptedException {
    ExecutorService threadExecutor = Executors.newFixedThreadPool(1);
    CompletableFuture c1 = new CompletableFuture();
    CompletableFuture c2 = new CompletableFuture();
    Future<String> future = threadExecutor.submit(() -> {
        try {
            c1.complete(null);
            Thread.sleep(10000);
            c2.complete("normal");
        } catch (InterruptedException e) {
            c2.complete("interrupted");
        }
        return "aaa";
    });
    c1.join(); // waits for the task start
    // future.get(); // awaits the completion
    System.out.println("cancel:     " + future.cancel(true));
    //System.out.println("cancel:     " + future.cancel(false));
    System.out.println("isDone:     " + future.isDone());
    System.out.println("isCanceled: " + future.isCancelled());
    System.out.println("task:       " + c2.join());
}