亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.430618.com 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

1、為什么廢棄Thread的stop函數?

對于有多線程開發經驗的開發者,應該大多數在開發過程中都遇到過這樣的需求,就是在某種情況下,希望立即停止一個線程。

比如:做Android App開發,當打開一個界面時,需要開啟線程請求網絡獲取界面的數據,但有時候由于網絡特別慢,用戶沒有耐心等待數據獲取完成就將界面關閉,此時就應該立即停止線程任務,不然一般會內存泄露,造成系統資源浪費,如果用戶不斷地打開又關閉界面,內存泄露會累積,最終導致內存溢出,APP閃退。

可能有不少開發者用過Thread的stop去停止線程,當然此函數確實能停止線程,不過JAVA官方早已將它廢棄,不推薦使用,這是為什么?

  1. stop是通過立即拋出ThreadDeath異常,來達到停止線程的目的,此異常拋出有可能發生在任何一時間點,包括在catch、finally等語句塊中,但是此異常并不會引起程序退出(筆者只測試了Java8)。
  2. 由于有異常拋出,導致線程會釋放全部所持有的鎖,極可能引起線程安全問題。

由于以上2點,stop這種方式停止線程是不安全的。

下面是stop的源碼(Java8):

 @Deprecated
 public final void stop() {
 SecurityManager security = System.getSecurityManager();
 if (security != null) {
 checkAccess();
 if (this != Thread.currentThread()) {
 security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
 }
 }
 // A zero status value corresponds to "NEW", it can't change to
 // not-NEW because we hold the lock.
 if (threadStatus != 0) {
 resume(); // Wake up thread if it was suspended; no-op otherwise
 }
 // The VM can handle all thread states
 stop0(new ThreadDeath());
 }
 
 private native void stop0(Object o);

上述源碼中關鍵代碼就是stop0(new ThreadDeath())函數,這是Native函數,傳遞的參數是ThreadDeath,ThreadDeath是一個異常對象,該對象從Native層拋到了Java層,從而導致線程停止,不過此異常并不會引起程序退出。

很多時候為了保證數據安全,線程中會編寫同步代碼,如果當線程正在執行同步代碼時,此時調用stop,引起拋出異常,導致線程持有的鎖會全部釋放,此時就不能確保數據的安全性,出現無法預期的錯亂數據,還有可能導致存在需要被釋放的資源得不到釋放,引發內存泄露。所以用stop停止線程是不推薦的。

2、用Thread的interrupt結束線程

其實調用Thread對象的interrupt函數并不是立即中斷線程,只是將線程中斷狀態標志設置為true,當線程運行中有調用其阻塞的函數(Thread.sleep,Object.wait,Thread.join等)時,阻塞函數調用之后,會不斷地輪詢檢測中斷狀態標志是否為true,如果為true,則停止阻塞并拋出InterruptedException異常,同時還會重置中斷狀態標志;如果為false,則繼續阻塞,直到阻塞正常結束。

因此,可以利用這種中斷機制來控制結束線程的運行。只要理解機制,代碼的實現其實比較簡單。

2.1、結束未使用阻塞函數的線程

public class Main {
 public static void main(String[] args) {
 InnerClass innerClass = new InnerClass();
 Thread thread = new Thread(innerClass);
 thread.start();
 long i = System.currentTimeMillis();
 while (System.currentTimeMillis() - i < 10 * 1000) {
 thread.isAlive();
 }
 thread.interrupt();
 }
 static class InnerClass implements Runnable {
 @Override
 public void run() {
 System.err.println("start work");
 while (!Thread.currentThread().isInterrupted()) {
 System.out.println("doing work");
 }
 System.err.println("done work");
 }
 }
}

思路其實就是用isInterrupted來判斷線程是否處于中斷狀態,若是中斷狀態,則跳出正在執行的任務,使線程結束運行。

2.2、結束使用阻塞函數的線程

public class Main {
 public static void main(String[] args) {
 InnerClass innerClass = new InnerClass();
 Thread thread = new Thread(innerClass);
 thread.start();
 long i = System.currentTimeMillis();
 while (System.currentTimeMillis() - i < 10 * 1000) {
 thread.isAlive();
 }
 thread.interrupt();
 }
 static class InnerClass implements Runnable {
 @Override
 public void run() {
 System.err.println("start work");
 while (!Thread.currentThread().isInterrupted()) {
 System.out.println("doing work");
 try {
 Thread.sleep(1000);
 } catch (InterruptedException e) {
 e.printStackTrace();
 Thread.currentThread().interrupt();
 }
 }
 System.err.println("done work");
 }
 }
}

思路同2.1,需要注意的是,調用sleep函數觸發InterruptedException異常時,在catch代碼塊中需調用interrupt函數,使線程再次處于中斷狀態,使while循環條件為false,使線程跳出循環,結束運行。若不調用,while循環為死循環,線程無法結束。

2.3、關于Thread的靜態函數interrupted與Thread的對象函數isInterrupted

先對比下2函數的源碼:

 public static boolean interrupted() {
 return currentThread().isInterrupted(true);
 }
 public boolean isInterrupted() {
 return isInterrupted(false);
 }
 /**
 * Tests if some Thread has been interrupted. The interrupted state
 * is reset or not based on the value of ClearInterrupted that is
 * passed.
 */
 private native boolean isInterrupted(boolean ClearInterrupted);

從源碼中可以看出,2函數都是調用了Native函數private native boolean isInterrupted(boolean ClearInterrupted);,前者調用傳的參數為true,所以,調用interrupted函數,會在檢測線程中斷狀態標志是否為true后,還會將中斷狀態標志重置為false。而isInterrupted函數只是檢測線程中斷狀態標志。

分享到:
標簽:線程 中斷 Java
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定