7

Given this code...

public class SimpleTest {

  @Test
  public void testCompletableFuture() throws Exception {
    Thread thread = new Thread(SimpleTest::longOperation);
    thread.start();

    bearSleep(1);

    thread.interrupt();

    bearSleep(5);
  }

  public static void longOperation(){
    System.out.println("started");
    try {

      boolean b = true;
      while (true) {
        b = !b;
      }

    }catch (Exception e){
      System.out.println("exception happened hurray!");
    }
    System.out.println("completed");
  }

  private static void bearSleep(long seconds){
    try {
      TimeUnit.SECONDS.sleep(seconds);
    } catch (InterruptedException e) {}
  }
}

Imagine that instead of this while(true) you have something that does not throw interrupted execution (for example, a recursive function that actually calculates something).

How do you kill this thing? And why is it not dying?

Note if I don't put Exception type there and use InterruptedException it won't even compile, saying that "interrupted exception will never be thrown" which I don't understand why. Maybe I want to interrupt it manually...

Null
  • 1,950
  • 9
  • 30
  • 33
vach
  • 10,571
  • 12
  • 68
  • 106

2 Answers2

4

I assume you are referring to this segment of code:

try {
    boolean b = true;
    while (true) {
        b = !b;
    }
} catch(Exception e) {
    System.out.println("exception happened hurray!");
}

The reason you cannot catch an InterruptedException here is because there is nothing inside of that block that can throw an InterruptedException. interrupt() itself will not break the thread out of the loop, instead, it essentially sends a signal to the thread to tell it to stop what it's doing and do something else. If you want interrupt() to break the loop, try this:

boolean b = true;
while (true) {
    b = !b;
    // Check if we got interrupted.
    if(Thread.interrupted()) {
        break; // Break out of the loop.
    }
}

Now the thread will check if it got interrupted, and break out of the loop once it has. No try-catch necessary.

Minty Fresh
  • 663
  • 4
  • 14
  • 1
    Please remember that with [Thread.interrupted()](http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#interrupted%28%29) *The interrupted status of the thread is cleared by this method.* – OldCurmudgeon Mar 12 '15 at 16:50
  • 3
    That's true. If you want to preserve the status of the `interrupted` flag, the instance method [Thread.isInterrupted()](http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#isInterrupted%28%29) should be used instead. – Minty Fresh Mar 12 '15 at 16:53
2

Thread#interrupt is more or less implemented with a flag. If the thread is blocked on some actions, ex: IO or synchronization primitives (see Javadoc), the thread is unblocked and an InterruptedException, is thrown in that thread. Otherwise, a simple status flag is set indicating that the thread was interrupted.

Your code needs to check for that status with Thread#interrupted() or Thread#isInterrupted() (or handle the InterruptedException).

Note that checking for the status with the static method clears the status.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724