Why Thread.stop and Thread.suspend Are Deprecated and How to Gracefully Stop Threads in Java
This article explains why the Thread.stop and Thread.suspend methods were deprecated in modern Java, demonstrates the problems they cause with concrete code examples, and presents two safe alternatives—using a shared flag and the interrupt mechanism—to gracefully terminate threads without risking deadlocks or resource leaks.
In recent Java versions, the methods Thread.stop and Thread.suspend are marked as @Deprecated because they can lead to unsafe thread termination, resource leaks, and deadlocks. This article explores the reasons behind their removal and shows how to stop threads safely.
1. The End of stop
The JDK source comment for stop reads “Forces the thread to stop executing.” This abrupt termination releases all monitors held by the thread, potentially leaving shared data in an inconsistent state.
Example demonstrating the problem:
public static void main(String[] args) throws InterruptedException {
Object o1 = new Object();
Object o2 = new Object();
Thread t1 = new Thread(() -> {
synchronized (o1) {
synchronized (o2) {
try {
System.out.println("t1获取到锁");
Thread.sleep(5000);
System.out.println("t1结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t1.start();
Thread.sleep(1000);
Thread t2 = new Thread(() -> {
synchronized (o1) {
synchronized (o2) {
try {
System.out.println("t2获取到锁");
Thread.sleep(5000);
System.out.println("t2结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t2.start();
t1.stop(); // abrupt termination
}When t1.stop() is called, the thread releases both o1 and o2 immediately, allowing t2 to acquire the locks and finish, while t1 never executes the code after sleep . This can cause lost updates, unreleased resources, or broken invariants.
Two recommended ways to stop a thread gracefully:
Use a shared volatile flag that the worker thread checks periodically.
Use Thread.interrupt() and let the thread respond to InterruptedException or Thread.currentThread().isInterrupted() .
Flag‑based example:
volatile static boolean flag = false;
public static void main(String[] args) throws InterruptedException {
Object o1 = new Object();
Thread t1 = new Thread(() -> {
synchronized (o1) {
try {
System.out.println("t1获取到锁");
while (!flag) {
Thread.sleep(5000); // business logic
}
System.out.println("t1结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
Thread.sleep(1000);
Thread t2 = new Thread(() -> {
synchronized (o1) {
try {
System.out.println("t2获取到锁");
Thread.sleep(5000);
System.out.println("t2结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t2.start();
flag = true; // signal termination
}Interrupt‑based example:
public static void main(String[] args) throws InterruptedException {
Object o1 = new Object();
Thread t1 = new Thread(() -> {
synchronized (o1) {
System.out.println("t1获取到锁");
while (!Thread.currentThread().isInterrupted()) {
for (int i = 0; i < 100; i++) {
if (i == 50) System.out.println();
System.out.print(i + " ");
}
System.out.println();
}
System.out.println("t1结束");
}
});
t1.start();
Thread t2 = new Thread(() -> {
synchronized (o1) {
try {
System.out.println("t2获取到锁");
Thread.sleep(5000);
System.out.println("t2结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t2.start();
t1.interrupt(); // graceful interruption
}Both approaches allow the thread to finish its current logical unit before exiting, avoiding the abrupt lock release that stop causes.
2. The End of suspend
Thread.suspend pauses a thread without releasing the locks it holds, which can easily lead to deadlocks. If an exception occurs before resume is called, the locked resources remain unavailable.
Example that creates a deadlock:
public static void main(String[] args) throws InterruptedException {
Object o1 = new Object();
Object o2 = new Object();
Thread t1 = new Thread(() -> {
synchronized (o1) {
System.out.println("t1获取到o1锁开始执行");
try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println("t1执行结束");
}
});
t1.start();
Thread t2 = new Thread(() -> {
synchronized (o2) {
System.out.println("t2获取到o2开始执行");
try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }
synchronized (o1) {
System.out.println("t2获取到o1锁开始继续执行");
}
System.out.println("t2执行结束");
}
});
t2.start();
Thread.sleep(1000);
t1.suspend(); // holds o1
int i = 1/0; // simulated exception before resume
t1.resume();
}Because t1 remains suspended while holding o1 , t2 blocks forever waiting for that lock, resulting in a deadlock.
Consequently, both stop and suspend have been removed from the Java API, and developers are encouraged to use the flag or interrupt patterns shown above.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.