java.lang.InterruptedException is thrown when a Thread blocked in Object.wait(), Thread.join(), or Thread.sleep() is interrupted. Here we’ll look at these cases.
To demonstrate each of these cases we’ll create a simple implementations of java.lang.Thread class that will be interrupted from the main method, hence unblocked from blocking calls.
Thread blocked on Object.wait()
To demonstrate the first case, when a Thread is blocked in Object.wait() method, we’ll use Thread implementation where it obtains object’s lock and waits on it for notification from other Thread:
static class Waiter extends Thread { private Object lock = new Object(); @Override public void run() { try { System.out.println("Waiter running..."); synchronized (lock) { lock.wait(); } } catch (InterruptedException e) { System.out.println("Waiter thread interrupted!"); e.printStackTrace(); } } }
Well, this example is contrived, but is enough for our case – the thread is blocked.
Note: the correct way to use Object.wait() is to call in inside a loop, which checks for end condition. The reason is that JVM can spuriously wake up a Thread – we’ll write a separate post about this.
Now let’s interrupt the Waiter, when it is waiting in lock.wait() method:
public static void main(String[] args) throws Exception { Thread waiter = new Waiter(); waiter.start(); // give the waiter some time to lock itself TimeUnit.SECONDS.sleep(1); waiter.interrupt(); }
As can be seen in logs, the thread has been unblocked:
Waiter running... Waiter thread interrupted! java.lang.InterruptedException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:502) at com.farenda.java.lang.ThreadInterrupted$Waiter.run(ThreadInterrupted.java:14)
Interrupted Thread.join()
The same happens when a Thread is waiting for another Thread to die using its join() method. This is because the Thread.join() is implemented as a loop that internally calls Object.wait() as can be observe in the exception stacktrace below:
static class Cleaner extends Thread { private final Thread other; public Cleaner(Thread other) { this.other = other; } @Override public void run() { try { System.out.println("Cleaner running..."); // Wait for the other thread's death: other.join(); System.out.println("Not waiting..."); } catch (InterruptedException e) { System.out.println("Cleaner thread interrupted!"); e.printStackTrace(); } } }
Again let’s run the code and then interrupt the thread:
public static void main(String[] args) throws Exception { Thread cleaner = new Cleaner(Thread.currentThread()); cleaner.start(); // give some time to call join() TimeUnit.MILLISECONDS.sleep(100); cleaner.interrupt(); TimeUnit.MILLISECONDS.sleep(50); }
As you can see, the message “Not waiting…” is never printed. What’s more interesting, the InterruptedException has been thrown from Object.wait() method:
Cleaner running... Cleaner thread interrupted! java.lang.InterruptedException at java.lang.Object.wait(Native Method) at java.lang.Thread.join(Thread.java:1249) at java.lang.Thread.join(Thread.java:1323) at com.farenda.java.lang.ThreadInterrupted$Cleaner.run(ThreadInterrupted.java:34)
Interrupted Thread.sleep()
The last example of java.lang.InterruptedException is from interrupted Thread.sleep() – java.util.concurrent.TimeUnit is just a wrapper around Thread.sleep() that allows to express time in human readable way:
static class Sleeper extends Thread { @Override public void run() { try { System.out.println("Sleeper running..."); TimeUnit.SECONDS.sleep(10); } catch (InterruptedException e) { System.out.println("Sleeper thread interrupted!"); e.printStackTrace(); } } }
Again, simple code using Thread.interrupt() to interrupt a thread waiting on blocking Thread.sleep() call:
public static void main(String[] args) throws Exception { Thread sleeper = new Sleeper(); sleeper.start(); // give it some time to call sleep() TimeUnit.MILLISECONDS.sleep(100); sleeper.interrupt(); }
Note that unlike Thread.join() this one doesn’t call Object.wait() underneath:
Sleeper running... Sleeper thread interrupted! java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at java.lang.Thread.sleep(Thread.java:340) at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386) at com.farenda.java.lang.ThreadInterrupted$Sleeper.run(ThreadInterrupted.java:48)
References:
- How to use Thread.join()
- Check out Java Concurrency Tutorial for more cool things!