Service 中啟動的執行緒若不響應中斷信號,會導致 Service 停止後執行緒仍在背景運行(洩漏)。正確終止流程:「設定標誌位 → 呼叫 interrupt() → 等待執行緒結束 → 清理資源」。
public class DaemonThread extends Thread {
private volatile boolean running = true;
private final Object[] args;
private final Config config;
public DaemonThread(Object[] args, Config config) {
this.args = args;
this.config = config;
}
@Override
public void run() {
try {
while (running && !Thread.currentThread().isInterrupted()) {
// 執行週期性工作
runDaemon(args, config);
// 可中斷的睡眠(響應 interrupt)
Thread.sleep(UPDATE_INTERVAL);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 重設中斷狀態
} finally {
cleanup(); // 釋放資源:關閉連線、檔案、註冊表等
}
}
public void shutdown() {
running = false;
interrupt(); // 打斷 sleep/wait/join
}
}
public class DaemonService extends Service {
private DaemonThread daemonThread;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (daemonThread == null || !daemonThread.isAlive()) {
daemonThread = new DaemonThread(args, config);
daemonThread.start();
}
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
if (daemonThread != null) {
daemonThread.shutdown();
try {
daemonThread.join(3000); // 最多等待 3 秒
} catch (InterruptedException ignored) {}
daemonThread = null;
}
}
}
| 機制 | 作用 | 注意事項 |
|---|---|---|
volatile boolean running | 跨執行緒可見性標誌 | 需配合 interrupt 使用 |
Thread.interrupt() | 打斷阻塞操作 | 需在 run() 中捕獲 InterruptedException |
Thread.sleep() | 可中斷睡眠 | 優於 while(true) 空轉 |
join(timeout) | 等待執行緒結束 | 設定超時避免 ANR |
// Kotlin Coroutine (推薦)
class DaemonService : Service() {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
scope.launch {
while (isActive) { // 自動檢查取消
runDaemon()
delay(UPDATE_INTERVAL) // 可取消延遲
}
}
return START_STICKY
}
override fun onDestroy() {
scope.cancel() // 取消所有協程
super.onDestroy()
}
}
running = false 不呼叫 interrupt() → 睡眠中無法立即停止InterruptedException 後不重設 interrupt() → 中斷狀態丟失onDestroy 中直接 return 不等待執行緒 → 資源洩漏stop()/suspend()/resume() → 已棄用、不安全遵循「協作式中斷」模式,配合現代並發框架,能確保 Service 與執行緒乾淨、可靠地結束。