正確中斷java線程

來源:互聯網
上載者:User
不提倡的stop()方法
臭名昭著的stop()停止線程的方法已不提倡使用了,原因是什麼呢?
 當在一個線程對象上調用stop()方法時,這個線程對象所啟動並執行線程就會立即停止,並拋出特殊的ThreadDeath()異常。這裡的“立即”因為太“立即”了,
假如一個線程正在執行:

synchronized void {
x = 3;
y = 4;
}

  由於方法是同步的,多個線程訪問時總能保證x,y被同時賦值,而如果一個線程正在執行到x = 3;時,被調用了 stop()方法,即使在同步塊中,它也乾脆地stop了,這樣就產生了不完整的殘廢資料。而多線程編程中最最基礎的條件要保證資料的完整性,所以請忘記 線程的stop方法,以後我們再也不要說“停止線程”了。

   如何才能“結束”一個線程?

interupt()中斷線程

一個線程從運行到真正的結束,應該有三個階段:

  1. 正常運行.
  2. 處理結束前的工作,也就是準備結束.
  3. 結束退出.

那麼如何讓一個線程結束呢?既然不能調用stop,可用的只的interrupt()方法。但interrupt()方法只是改變了線程的運行狀態,如何讓它退出運行?對於一般邏輯,只要線程狀態已經中斷,我們就可以讓它退出,這裡我們定義一個線程類ThreadA,所以這樣的語句可以保證線程在中斷後就能結束運行:

 while(!isInterrupted()){
正常邏輯
}

,一個測試類別,ThreadDemo
  這樣ThreadDemo調用interrupt()方法,isInterrupted()為true,就會退出運行。但是如果線程正在執行wait,sleep,join方法,你調用interrupt()方法,這個邏輯就不完全了。
我們可以這樣處理:

 public void run(){

while(!isInterrupted()){
try{
正常工作
}catch(InterruptedException e){
//nothing
}

}
}
}

想一想,如果一個正在sleep的線程,在調用interrupt後,會如何?wait方法檢查到isInterrupted()為true,拋出異常, 而你又沒有處理。而一個拋出了InterruptedException的線程的狀態馬上就會被置為非中斷狀態,如果catch語句沒有處理異常,則下一 次迴圈中isInterrupted()為false,線程會繼續執行,可能你N次拋出異常,也無法讓線程停止。
這個錯誤情況的執行個體代碼
ThreadA
public class ThreadA extends Thread ...{
   int count=0;
   public void run()...{
       System.out.println(getName()+"將要運行...");
       while(!this.isInterrupted())...{
           System.out.println(getName()+"運行中"+count++);
           try...{
               Thread.sleep(400);
           }catch(InterruptedException e)...{
               System.out.println(getName()+"從阻塞中退出...");
               System.out.println("this.isInterrupted()="+this.isInterrupted());

           }
       }
       System.out.println(getName()+"已經終止!");
   }
}

ThreadDemopublic class ThreadDemo ...{
    
    public static void main(String argv[])throws InterruptedException...{
        ThreadA ta=new ThreadA();
        ta.setName("ThreadA");
        ta.start();
        Thread.sleep(2000);
        System.out.println(ta.getName()+"正在被中斷...");
        ta.interrupt();
        System.out.println("ta.isInterrupted()="+ta.isInterrupted());
    }

}

 那麼如何能確保線程真正停止?線上程同步的時候我們有一個叫“二次惰性檢測”(double check),能在提高效率的基礎上又確保線程真正中同步控制中。那麼我把線程正確退出的方法稱為“雙重安全退出”,即不以isInterrupted ()為迴圈條件。而以一個標記作為迴圈條件:
正確的ThreadA代碼是: 

public class ThreadA extends Thread ...{
    private boolean isInterrupted=false;
   int count=0;
   
   public void interrupt()...{
       isInterrupted = true;
       super.interrupt();
      }
   
   public void run()...{
       System.out.println(getName()+"將要運行...");
       while(!isInterrupted)...{
           System.out.println(getName()+"運行中"+count++);
           try...{
               Thread.sleep(400);
           }catch(InterruptedException e)...{
               System.out.println(getName()+"從阻塞中退出...");
               System.out.println("this.isInterrupted()="+this.isInterrupted());

           }
       }
       System.out.println(getName()+"已經終止!");
   }
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.