Thread.stop()?stop() / suspend() / resume() 已棄用:強制釋放鎖導致數據不一致、對象處於破損狀態。正確做法是協作式停止——線程定期檢查標誌位,主動退出 run()。
public class StoppableTask extends Thread {
// volatile 保證跨線程可見性:主線程寫入,工作線程讀取
private volatile boolean stopRequested = false;
@Override public void run() {
while (!stopRequested) {
// 執行業務邏輯
doWork();
// 適當休眠降低 CPU 佔用
sleepQuietly(720);
}
// 清理資源、釋放鎖、關閉連接
cleanup();
System.out.println("線程已優雅停止");
}
public void requestStop() { stopRequested = true; }
private void doWork() { System.out.println("Working..."); }
private void cleanup() { /* 關閉流、歸還連接池等 */ }
private void sleepQuietly(long ms) {
try { Thread.sleep(ms); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
}
public static void main(String[] args) throws InterruptedException {
StoppableTask t = new StoppableTask();
t.start();
Thread.sleep(5000); // 讓它跑 5 秒
t.requestStop(); // 發送停止信號
t.join(); // 等待線程實際結束
System.out.println("主線程結束");
}
}
| 細節 | 原因 | 代碼體現 |
|---|---|---|
volatile | 禁止指令重排、強制從主內存讀寫,保證主線程修改對工作線程立即可見 | private volatile boolean stopRequested |
| 檢查點位置 | 放在循環條件、耗時操作前後、I/O 等待後,確保「及時響應」 | while (!stopRequested) |
處理 InterruptedException | 休眠/等待時被 interrupt() 喚醒,應重新設置中斷標誌或直接退出 | Thread.currentThread().interrupt(); |
| 資源清理 | 退出循環後在 run() 末尾釋放鎖、關閉流、歸還連接池 | cleanup() |
join() 等待 | 主線程確認工作線程完全結束再繼續,避免殘留資源洩漏 | t.join() |
interrupt() 雙重保障public class HybridStoppableTask implements Runnable {
private volatile boolean stop = false;
@Override public void run() {
while (!stop && !Thread.currentThread().isInterrupted()) {
try {
doWork();
Thread.sleep(500);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 重新設置標誌
break; // 直接跳出
}
}
cleanup();
}
public void shutdown() {
stop = true;
// 若線程阻塞在 sleep/wait/join,interrupt() 能喚醒它
Thread.currentThread().interrupt(); // 注意:這裡需持有線程引用
}
}
ExecutorService pool = Executors.newSingleThreadExecutor(); Future<?> future = pool.submit(new StoppableTask()); // ... 業務邏輯 ... future.cancel(true); // true = mayInterruptIfRunning pool.shutdown(); pool.awaitTermination(10, TimeUnit.SECONDS);
Future.cancel(true) 內部調用 thread.interrupt();Thread.currentThread().isInterrupted() 檢查實現響應;Thread 洩漏。