InterruptedException — Thread Interrupt Fix
An InterruptedException is thrown when a thread is interrupted while it is sleeping, waiting, or otherwise blocked in an interruptible operation. It is a checked exception and signals that another thread has requested the current thread to stop.
Description
This exception is part of Java’s concurrency API. It fires when Thread.interrupt() is called on a thread that is in one of these states:
Thread.sleep()Object.wait()Thread.join()- Blocking
I/O(e.g.,InputStream.read()) Lock.lockInterruptibly()Future.get()
The critical detail: catching and swallowing InterruptedException clears the interrupt flag, silently preventing higher-level code from detecting the interrupt.
Common Causes
// Cause 1: Swallowing InterruptedException (most common bug)
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// Bad: interrupt flag is now cleared
}
// Cause 2: Calling interruptible method without handling the exception
public void waitForData(Queue<String> queue) throws InterruptedException {
String data = queue.take(); // InterruptedException if interrupted
}
// Cause 3: Thread pool task ignoring interrupts
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(() -> {
while (running) {
processNext(); // May block and throw InterruptedException
}
});
// Cause 4: Nested interruptible calls without re-interrupting
public void loadData() {
try {
Thread.sleep(5000); // InterruptedException
fetchFromDatabase(); // Another interruptible call
} catch (InterruptedException e) {
// Forgot to re-interrupt — interrupt is lost
}
}
Solutions
Fix 1: Re-set the interrupt flag when catching InterruptedException
// Wrong — swallows the interrupt
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
log.warn("Sleep interrupted");
}
// Correct — preserves the interrupt status
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // Re-set the flag
log.warn("Sleep interrupted");
}
Fix 2: Propagate the exception instead of catching it
// Correct — let the caller decide how to handle the interrupt
public void pollQueue() throws InterruptedException {
String item = queue.poll(5, TimeUnit.SECONDS);
if (item != null) {
process(item);
}
}
Fix 3: Use Thread.currentThread().interrupt() in catch blocks
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Task task = taskQueue.take();
task.execute();
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // Restore interrupt
break; // Exit the loop
}
}
cleanup();
}
Fix 4: Use ExecutorService.shutdownNow() to interrupt tasks
ExecutorService executor = Executors.newFixedThreadPool(4);
executor.submit(this::processData);
// To stop gracefully
executor.shutdownNow(); // Sends interrupt to all running tasks
executor.awaitTermination(10, TimeUnit.SECONDS);
Prevention Checklist
- Never catch
InterruptedExceptionwithout either re-setting the interrupt flag or re-throwing. - Declare
throws InterruptedExceptionon methods that call interruptible APIs. - Use
Thread.currentThread().interrupt()in catch blocks to preserve the interrupt. - Check
Thread.currentThread().isInterrupted()in long-running loops.
Related Errors
- ThreadDeath — deprecated thread termination mechanism.
- IllegalMonitorStateException — related to synchronization failures.
- IOException — blocking I/O may throw InterruptedException indirectly.
Comments