Explanation
What just happened
main called worker.interrupt(). That doesn’t kill anything: it sets a flag on worker. worker was asleep, and a sleeping thread checks the flag right away, so sleep() threw InterruptedException. worker’s own catch block cleaned up and returned.
Try the what-if switch
- busy loop checks the flag: a thread doing CPU work never blocks, so nothing throws. It has to look at
isInterrupted()itself, and it stops at its next check. - exception swallowed: throwing
InterruptedExceptionclears the flag. The emptycatchhides the request, the loop seesfalse, and the thread never stops.
Why it works this way
Killing a thread from outside could leave locks held and objects half-updated. So Java makes stopping cooperative: you ask, and the thread stops at a safe point in its own code. Thread.stop() was the unsafe version. It still runs on JDK 8 to 19, throws from JDK 20, and is gone in JDK 27.
Handling InterruptedException
Pick one:
// 1. Let it propagate: declare throws InterruptedException.
// 2. Or restore the flag so callers can still see it:
catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
Executors rely on this too: shutdownNow() interrupts every worker, and only tasks that respond actually stop.
Common questions
How do you stop a thread in Java?
Call interrupt() and let the thread stop itself. Blocking calls like sleep(), wait(), join() and take() throw InterruptedException. A loop doing CPU work must check Thread.currentThread().isInterrupted().
Why does my thread keep running after interrupt()?
Usually an empty catch swallowed InterruptedException. Throwing it clears the interrupt flag, so the request is lost. Restore it with Thread.currentThread().interrupt(), or let the exception propagate.
Can I still use Thread.stop()?
No. On JDK 8 to 19 it still kills the thread, unsafely: it could leave locks held and objects half-updated. JDK 20 to 25 throw UnsupportedOperationException, and JDK 27 has removed it.
Verified: this timeline matches a real program, checked in CI on JDK 21 and 25. How we verify. Unclear or wrong? Tell us