Why set the interrupt bit in a Callable

2019-03-04 15:29发布

问题:

So, this resource (http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html) suggest to set the interrupt bit in a Thread when that Thread does not deal with the interrupt itself, "so that code higher up on the call stack can learn of the interruption and respond to it if it wants to."

Let's say I'm using an ExecutorService to run something in a different Thread. I construct a Callable and pass this Callable into ExecutorService.submit(), which returns a Future. If the Callable gets interrupted and then resets the interrupt bit, the associated Future will not throw an InterruptedException when Future.get() is called. So what would be the purpose of setting the interrupted bit in the Callable if this Future is the only way the main Thread has access to the spawned Thread.

class MyCallable implements Callable<String> {
  @Override
  public String call() {
    while (!Thread.currentThread().isInterrupted()) {
    }
    Thread.currentThread().interrupt();
    return "blah";
  }
}

 ExecutorService pool = makeService();
 Future<String> future = pool.submit(new MyCallable());
 // Callable gets interrupted and the Callable resets the interrupt bit.
 future.get(); // Does not thrown an InterruptedException, so how will I ever know that the Callable was interrupted?

回答1:

You are correct that the interrupt flag is not passed between the 2 threads in this scenario (that's how the built in ExecutorService was designed for whatever reason). If you want the main thread to see the interrupted status of the callable, then you must throw InterruptedException from your call method.

class MyCallable implements Callable<String> {
  @Override
  public String call() {
    // ...
    if(Thread.currentThread().isInterrupted()) {
      throw new InterruptedException();
    }
    return "blah";
  }
}

Note, you still won't get InterruptedException directly from Future.get() in this scenario. since it was thrown by the callable, it will be wrapped in an ExecutionException (this is so you can distinguish between an interruption of the callable and an interruption of the main thread).



回答2:

Interrupting a thread is supposed to terminate it, but in a less fragile way than kill(). The interrupted state of the thread is checked only during various blocking operations.

If your thread has been interrupted during one of these operations, an InterruptedException is thrown. When this happens, you want to exit cleanly, as quickly as you can. So, what should a Callable do if the executor service thread is interrupted?

If its action is short, one valid option is to just complete that action normally, but set the interrupted state on the thread so that the executor service will shut down after this action completes.

If the action is longer, you may want to instead throw an exception telling the caller that the action was interrupted.