這三個方法已棄用:stop() 導致鎖強制釋放,數據不一致;suspend()/resume() 極易死鎖。正確終止需協作式:線程主動檢查終止信號並安全退出。
public class FlagTask extends Thread {
// volatile 保證可見性,防止 JIT 優化緩存
private volatile boolean running = true;
public void shutdown() {
running = false; // 請求終止
}
@Override
public void run() {
while (running) { // 輪詢檢查
// 執行非阻塞業務邏輯
doWork();
}
// 清理資源、記錄日誌
cleanup();
}
private void doWork() { /* ... */ }
private void cleanup() { /* ... */ }
}
public class InterruptibleTask implements Runnable {
@Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) { // 檢查中斷狀態
// 可中斷阻塞操作:sleep、wait、join、Channel IO、Lock.lockInterruptibly
TimeUnit.SECONDS.sleep(1);
doWork();
}
} catch (InterruptedException e) {
// 睡眠中被中斷:異常捕獲後中斷狀態被清除
Thread.currentThread().interrupt(); // 重新設置中斷標誌(良好習慣)
} finally {
cleanup(); // 確保資源釋放
}
}
private void doWork() { /* ... */ }
private void cleanup() { /* ... */ }
}
// 使用
Thread t = new Thread(new InterruptibleTask());
t.start();
// ...
t.interrupt(); // 發送中斷請求
interrupt() 僅設置中斷標誌,不直接停止線程InterruptedException 並清除標誌Thread.interrupted() 或 isInterrupted() 檢查public class SocketServerTask extends Thread {
private volatile ServerSocket serverSocket;
@Override
public void run() {
try {
serverSocket = new ServerSocket(8080);
while (!Thread.currentThread().isInterrupted()) {
Socket client = serverSocket.accept(); // 阻塞,不可中斷
handleClient(client);
}
} catch (IOException e) {
// ServerSocket.close() 會導致 accept() 拋出 SocketException
if (!Thread.currentThread().isInterrupted()) {
log.error("ServerSocket error", e);
}
}
}
public void shutdown() {
try {
if (serverSocket != null) {
serverSocket.close(); // 觸發 accept() 異常退出
}
} catch (IOException e) {
log.error("Close server socket failed", e);
}
this.interrupt(); // 輔助中斷
}
private void handleClient(Socket client) { /* ... */ }
}
ServerSocket.accept()/InputStream.read() 不響應中斷Selector/Channel 原生支持中斷,優先選用public abstract class GracefulTask implements Runnable {
private volatile boolean shutdownRequested = false;
public final void shutdown() {
shutdownRequested = true;
interrupt(); // 嘗試中斷阻塞
closeResources(); // 關閉底層資源
}
protected boolean isShutdownRequested() {
return shutdownRequested || Thread.currentThread().isInterrupted();
}
protected abstract void doWork() throws Exception;
protected abstract void closeResources();
@Override
public final void run() {
try {
while (!isShutdownRequested()) {
doWork();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Exception e) {
log.error("Task error", e);
} finally {
closeResources();
}
}
}
Future.cancel(true) + 超時監控