简体   繁体   中英

Interrupting a thread from itself

I do not understand why the thread does not throw an InterruptedException when interrupted itself.

I'm trying with following snippet:

public class InterruptTest {

 public static void main(String[] args) { MyThread t = new MyThread(); t.start(); try { t.join(); } catch (InterruptedException ex) { ex.printStackTrace(); } } private static class MyThread extends Thread { @Override public void run() { Thread.currentThread().interrupt(); } } }

In the API docs it says on the interrupt() method:

If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the Thread.join(), Thread.join(long), Thread.join(long, int), Thread.sleep(long), or Thread.sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.

I know this is an old question, but I think the answers above are actually not quite correct. (except @Skylion's, which doesn't really address the question...) :)

Thread.interrupt() does not throw any exceptions by itself. It does two things: First it simply sets an internal interrupted -flag and then it checks if the thread that it was called on is currently blocking on an activity like wait() , sleep() , or join() . If it finds one, then it wakes up that method and causes that method to throw the exception inside the thread it was called on (not from).

In the case where you call interrupt() from the thread itself, that thread obviously can't itself be currently blocking on one of those calls as it is currently executing your interrupt() call. So, only the internal interrupted -flag is set and no exception is thrown at all.

The next time you call one of the blocking methods (like sleep() in @OldCurmudgeon's example) from that thread, that method will notice the interrupted -flag and throw the InterruptedException .

If you don't ever call any of those methods, your thread will simply continue running until it terminates some other way and will never throw an InterruptedException . This is true even if you call interrupt() from a different thread.

So, to notice that your thread has been interrupted, you either need to frequently use one of the blocking methods that throws an InterruptedException and then quit when you receive one of those exceptions, or you need to frequently call Thread.interrupted() to check the internal interrupted -flag yourself and quit if it ever returns true . But you are also free to simply ignore the exception and the result from Thread.interrupted() completely and keep the thread running. So, interrupt() might be a little bit ambiguously named. It doesn't necessarily "interrupt" (as in "terminate") the Thread at all, it simply sends a signal to the thread that the thread can handle or ignore as it pleases. Much like a hardware interrupt signal on a CPU (which is probably where the name comes from).

To have the exception be thrown by the join() method in your main thread, you need to call interrupt() on that thread, rather than on MyThread , like so:

public static void main(String[] args) {
    MyThread t = new MyThread();
    t.start();
    try {
        t.join();
    } catch (InterruptedException ex) {
        System.out.println("Now it works:");
        ex.printStackTrace();
    }
}

private static class MyThread extends Thread {

    private final Thread parentThread;

    public MyThread() {
        parentThread = Thread.currentThread();
    }

    @Override
    public void run() {
        parentThread.interrupt();  // Call on main thread!!!
    }
}

See @markus-a's answer for what should have been the accepted answer here. (Mine should be deleted, but I can't do that while it's accepted).


Exceptions are always thrown on their own thread. You have two different threads: your main thread and the one you created. There's no way the exception thrown in MyThread can be caught in the main one.

Why interrupt the thread at all? Just use

return;

You're just being too quick - try this:

private static class MyThread extends Thread {

  @Override
  public void run() {
    try {
      Thread.currentThread().interrupt();
      Thread.sleep(5000);
    } catch (InterruptedException ex) {
      Logger.getLogger(Test.class.getName()).log(Level.SEVERE, "Oops", ex);
    }
  }
}

I get:

Oct 04, 2013 12:43:46 AM test.Test$MyThread run
SEVERE: Oops
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at test.Test$MyThread.run(Test.java:36)

note that you cannot propagate the exception out of the run method because run does not throw any exceptions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM