Question

Why doesn't setting the interrupt bit in a Callable cause the Future that represents the Callable to throw a TimeoutException when Future.get() is called?

public class ExecutorServiceTest extends MockitoTestCase {
  private static CountDownLatch latch1 = new CountDownLatch(1);

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

  void testInterrupt() throws Exception {
    ExecutorService pool = Executors.newFixedThreadPool(numThreads);
    Future<String> future = pool.submit(new TaskChecksForInterruptedExcAndDoesSetInterruptedBit());
    latch1.await(); // Don't interrupt the Callable until it actually starts processing
    pool.shutdownNow();
    try {
      future.get(100, TimeUnit.MILLISECONDS);
    } catch (final TimeoutException e) {
      // Why doesn't this get called!
      return;
    }
    fail();
  }
}
Was it helpful?

Solution

  1. the shutdownNow() call attempts to interrupt all running tasks. In this case the interruption is detected in your busy loop, so the code continues and the Callable returns "blah" (and not an exception)

  2. TimeoutException, according to the spec, is thrown only if the thread waits for the complete timeout period, but no result becomes available. Interruption doesn't fit into this scenario.

  3. Your usage of CountDownLatch is incorrect. You decrement it, but I see no call to latch1.await()

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top