Which Java methods throw InterruptedException, and what do they do to the interrupt status flag when they throw?
answer
- sleep / wait / join / take / put / await / acquire throw it
- throwing CLEARS the flag to false
- signal moves from flag -> exception
- after catch, isInterrupted() is false -> restore if needed
- synchronized & plain socket I/O are NOT interruptible
basics
~10 sBlocking methods like Thread.sleep(), Object.wait(), Thread.join(), and BlockingQueue.take()/put() throw InterruptedException. When they throw, they clear the interrupt flag back to false.
solid answer
~50 sThe interruptible blocking methods are the ones that make a thread wait: Thread.sleep, Object.wait (and timed wait), Thread.join, BlockingQueue.take/put and offer/poll with timeout, Lock.lockInterruptibly, Condition.await, Semaphore.acquire, CountDownLatch.await, Future.get, and similar java.util.concurrent waits. When any of them detects that the thread's interrupt status is set, it stops waiting and throws a checked InterruptedException — and importantly it clears the flag to false as part of throwing. The rationale is that the exception now carries the signal, so the flag and the exception aren't both 'live' at once. The practical consequences: after catching InterruptedException, isInterrupted() returns false, so if you can't propagate you must restore the flag with Thread.currentThread().interrupt(). Note that not all blocking is interruptible — entering a synchronized block, plain socket/stream I/O, and Lock.lock() do not throw InterruptedException and only have the flag set, requiring other techniques (closing the socket, lockInterruptibly) to cancel.
code
java · 8 linesThread.currentThread().interrupt(); // flag = true
try {
Thread.sleep(1000); // sees the set flag -> throws immediately
} catch (InterruptedException e) {
// flag is now FALSE here (cleared by the throw)
boolean stillSet = Thread.currentThread().isInterrupted(); // false
Thread.currentThread().interrupt(); // restore it if you can't propagate
}go deeper
Can name a couple of methods that throw InterruptedException (sleep, wait) and knows it signals interruption.
Lists the main interruptible blocking methods and knows that throwing clears the flag, hence the restore rule.
Explains why the flag is cleared (signal hand-off) and identifies non-interruptible blocking (synchronized, plain I/O) plus the workarounds.
Audits code paths for the least-interruptible operation, chooses interruptible primitives (lockInterruptibly, NIO channels), and bounds shutdown latency accordingly.
## Which methods throw it `InterruptedException` is a **checked** exception declared by Java's **interruptible blocking** operations — methods that put the thread into a waiting state and are designed to bail out early if interrupted. The common ones: - `Thread.sleep(...)` — timed pause. - `Object.wait()` / `wait(timeout)` — monitor wait. - `Thread.join()` / `join(timeout)` — wait for another thread to finish. - `java.util.concurrent`: `BlockingQueue.take()/put()` (and timed `poll/offer`), `Lock.lockInterruptibly()`, `Condition.await()`, `Semaphore.acquire()`, `CountDownLatch.await()`, `CyclicBarrier.await()`, `Future.get()`, `ExecutorService.invokeAll/awaitTermination`, etc. A quick mental model: **if a method makes the thread wait and is meant to be cancellable, it throws InterruptedException.** ## What happens to the flag when they throw When such a method notices the **interrupt status flag** is set (either it was already set on entry, or it becomes set while waiting), it: 1. abandons the wait, 2. **clears the flag back to `false`**, and 3. throws `InterruptedException`. **Why clear?** Java's design keeps the cancellation signal in exactly one place at a time. Before the throw it lived in the flag; after the throw it lives in the in-flight exception. If the method *also* left the flag set, callers might double-handle the interrupt. So the throw consumes the flag. ```text flag = true --(method detects it)--> throw InterruptedException, flag = false ``` ## Consequence you must remember Inside a `catch (InterruptedException e)`, calling `Thread.currentThread().isInterrupted()` returns **false** — the flag is already gone. That's exactly why the correct handling, when you can't propagate, is to **restore** it: `Thread.currentThread().interrupt()`. Otherwise the signal is lost. ## Not all blocking is interruptible (the important caveat) Some operations block but do **not** throw `InterruptedException`; an interrupt only sets the flag and the operation keeps waiting: - Acquiring a `synchronized` monitor lock. - `Lock.lock()` (the plain, uninterruptible form). - Classic blocking I/O: `InputStream.read()` on a socket, `Socket` connect/accept. To cancel those you need other tools: `Lock.lockInterruptibly()` instead of `lock()`, NIO `InterruptibleChannel`s (which throw `ClosedByInterruptException` and close on interrupt), or simply closing the socket so the blocked read throws an `IOException`. So interruption responsiveness is bounded by the *least* interruptible operation in your code path. ## Terms - **Checked exception:** one the compiler forces you to catch or declare (`InterruptedException` is checked). - **Interruptible blocking:** a wait that reacts to interrupt() by throwing. - **Monitor:** the lock associated with `synchronized`/`wait`/`notify`.
- If a thread's flag is already set before it calls sleep(), what happens?sleep() does not even begin to wait: it notices the set flag, clears it, and throws InterruptedException immediately. So a pending interrupt makes the very next interruptible blocking call throw at once.
- How do you make a thread blocked on a plain socket read respond to cancellation?Plain socket I/O is not interruptible, so interrupt() only sets the flag. Close the socket/stream from another thread — the blocked read then throws an IOException/SocketException and unwinds. NIO interruptible channels are the cleaner alternative, throwing ClosedByInterruptException on interrupt.
saying these in an interview costs you the question
- Believing the flag stays set after InterruptedException is thrown
- Assuming entering a synchronized block throws InterruptedException
- Thinking InterruptedException is unchecked
- Expecting plain socket reads to unblock on interrupt()