首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android 徹底終止 Service 執行緒:interrupt 機制與最佳實踐

     編輯:程式設計綜合問答

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
    }
}

Service 整合


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

現代替代:Coroutine / RxJava / ExecutorService


// 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 與執行緒乾淨、可靠地結束。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved