《永劫無間》迦南美杜莎捏臉資料分享
1. 如何停止一個執行緒?
官方停止執行緒的方法被廢棄了,所以不能直接停止執行緒,這麼做是非常不安全的。
2. 為什麼不能簡單停止一個執行緒?
因為,簡單停止一個執行緒會出現很多異常情況,比如:多執行緒讀取共享變數時,其中一個執行緒加鎖了,其它執行緒處於等待狀態,如果,將加鎖執行緒暫停了,那麼其它執行緒就會被堵塞在這裡,不能釋放,假如加鎖執行緒在等待其它執行緒中某個執行緒的釋放鎖,那麼,就會出現死鎖。所以,執行緒中的暫停方法也被廢棄了。如果,直接使用stop方法停止執行緒,執行緒立刻被回收,被堵塞的執行緒立刻獲得鎖許可權並加鎖,然後去操作共享變數,此時發現共享記憶體有一堆莫名資料或者狀態,這些資料原因是前一個執行緒在被停止時立刻被回收了,沒有來的及處理完成,就被其它執行緒獲得加鎖操作了,那麼,這個執行緒也會出現異常,甚至Crash。
3. 如何安全的停止一個執行緒?
通過執行緒自行結束,而不是強行停止,目標執行緒應當具有處理中斷能力。也是在使用執行緒過程中要通過結束任務從而停止執行緒。通過執行緒任務而停止執行緒,和停止執行緒結果上沒什麼區別,但是,和通過停止執行緒的方法結束執行緒的方式相比,結果有明顯區別,停止執行緒是不安全的做法,而通過邏輯控制結束任務從而結束執行緒卻是安全的做法。
通過邏輯中斷執行緒的方式:
1. 使用Thread內建的interrupted()(中止)方法:
@FastNative public static native boolean interrupted();
但是,線上程中要新增識別中止狀態的邏輯:
Thread thread = new Thread() { @Override public void run() { for (int idx = 0; idx < 1000000; idx++) { // interrupted() if (isInterrupted()) { break; } // TODO: 2020/6/1 } } }; thread.start(); // 呼叫中斷方法,傳送中斷執行緒狀態 thread.interrupt();
獲取中止狀態的方法有兩個,分別是isInterrupted()和interrupted(),其中interrupted()是靜態方法,兩個方法的區別:
isInterrupted():是簡單的讀取該執行緒的中斷狀態,不清空可以重複呼叫,直到狀態清空前一直返回true。
interrupted():是靜態方法,獲取該執行緒的中斷狀態,並清空狀態。中斷狀態呼叫後清空,後續再呼叫返回false。
2. volatile boolean 標誌位,就是自己實現中斷邏輯:
class InterruptThread extends Thread { public volatile boolean isStopped = false; @Override public void run() { super.run(); for (int idx = 0; idx < 100000; idx++) { if (isStopped) { return; } System.out.println("test"); } } } void test() { InterruptThread thread = new InterruptThread(); thread.start(); thread.isStopped = true }