I track the progress of a task with a standard Future object. The following valid states for this task exist (as I see in the Guava code of the AbstractFuture class):
- Launch;
- Completion;
- Completed successfully or with an exception;
- Canceled;
- Interrupted.
Future.isDone() returns true if and only if the state is complete, canceled, or aborted. Future.isCancelled() returns true if and only if the state is interrupted or canceled.
Good, but I need to check if the task is completed. There is an obvious way to do this:
boolean isCompleted = future.isDone() && !future.isCancelled();
Unfortunately, the nasty concurrency error lurks here.
- Topic # 1 calls
Future.isCancelled() . The result is false because the task is still in progress. - Topic # 2 cancels the call to
future.cancel() . - Topic # 1 calls
Future.isDone() . The result is true now. - Evaluating the expression above gives
true , and this is the wrong answer.
How to avoid this problem?
source share