Java線程的傳說(1)——中斷線程Interrupted的用處

來源:互聯網
上載者:User

 中斷線程
—— interrupt() 

 一個正在啟動並執行線程除了正常的時間片中斷之外,能否被其他線程式控制制?或者說其他線程能否讓指定線程放棄CPU或者提前結束運行?
除了線程同步機制之外,還有兩種方法:
      
(1) Thread.stop(), Thread.suspend(), Thread.resume() 和Runtime.runFinalizersOnExit() 這些終止線程啟動並執行方法 。這些方法已經被廢棄,使用它們是極端不安全的。
      
(2) Thread.interrupt() 方法是很好的選擇。但是使用的時候我們必須好好理解一下它的用處。

 //無法中斷正在啟動並執行線程代碼   class TestRunnable implements Runnable{         public void run(){               while(true)               {                     System.out.println( "Thread is running..." );                     long time = System.currentTimeMillis();//去系統時間的毫秒數               while((System.currentTimeMillis()-time < 1000)) {                      //程式迴圈1秒鐘,不同於sleep(1000)會阻塞進程。               }                 }          }   }   public class ThreadDemo{            public static void main(String[] args){                  Runnable r=new TestRunnable();                  Thread th1=new Thread(r);                  th1.start();                  th1.interrupt();                    }   }  //運行結果:一秒鐘列印一次Thread is running...。程式沒有終止的任何跡象 

上面的代碼說明interrupt()並沒有中斷一個正在啟動並執行線程,或者說讓一個running中的線程放棄CPU。那麼interrupt到底中斷什麼。
      
首先我們看看interrupt究竟在幹什麼。
      
當我們調用th1.interrput()的時候,線程th1的中斷狀態(interrupted status) 會被置位。我們可以通過Thread.currentThread().isInterrupted() 來檢查這個布爾型的中斷狀態。
       
在Core Java中有這樣一句話:"沒有任何語言方面的需求要求一個被中斷的程式應該終止。中斷一個線程只是為了引起該線程的注意,被中斷線程可以決定如何應對中斷 "。好好體會這句話的含義,看看下面的代碼:

 //Interrupted的經典使用代碼   public void run(){           try{                ....                while(!Thread.currentThread().isInterrupted()&& more work to do){                       // do more work;                }           }catch(InterruptedException e){                       // thread was interrupted during sleep or wait           }           finally{                      // cleanup, if required           }   }  

很顯然,在上面代碼中,while迴圈有一個決定因素就是需要不停的檢查自己的中斷狀態。當外部線程調用該線程的interrupt
時,使得中斷狀態置位。這是該線程將終止迴圈,不在執行迴圈中的do more work了。

      
這說明: interrupt中斷的是線程的某一部分商務邏輯,前提是線程需要檢查自己的中斷狀態(isInterrupted())。

      
但是當th1被阻塞的時候,比如被Object.wait, Thread.join和Thread.sleep三種方法之一阻塞時。調用它的interrput()方法。可想而知,沒有佔用CPU啟動並執行線程是不可能給自己的中斷狀態置位的。這就會產生一個InterruptedException異常。

 //中斷一個被阻塞的線程代碼class TestRunnable implements Runnable{     public void run(){          try{    Thread.sleep(1000000); //這個線程將被阻塞1000秒       }catch(InterruptedException e){     e.printStackTrace();                     //do more work and return.          }     }}public class TestDemo2{      public static void main(String[] args) {            Runnable tr=new TestRunnable();            Thread th1=new Thread(tr);            th1.start(); //開始執行分線程        while(true){   th1.interrupt();  //中斷這個分線程        }      }}/*運行結果:   java.lang.InterruptedException: sleep interrupted        at java.lang.Thread.sleep(Native Method)        at TestRunnable.run(TestDemo2.java:4)        at java.lang.Thread.run(Unknown Source)*/

*
如果線程被阻塞,它便不能核查共用變數,也就不能停止。這在許多情況下會發生,例如調用
*
Object.wait()、ServerSocket.accept()和DatagramSocket.receive()時,他們都可能永
*
久的阻塞線程。即使發生逾時,在逾時期滿之前持續等待也是不可行和不適當的,所以,要使
*
用某種機制使得線程更早地退出被阻塞的狀態。很不幸運,不存在這樣一種機制對所有的情況
*
都適用,但是,根據情況不同卻可以使用特定的技術。使用Thread.interrupt()中斷線程正
*
如Example1中所描述的,Thread.interrupt()方法不會中斷一個正在啟動並執行線程。這一方法
*
實際上完成的是,線上程受到阻塞時拋出一個中斷訊號,這樣線程就得以退出阻塞的狀態。更
*
確切的說,如果線程被Object.wait, Thread.join和Thread.sleep三種方法之一阻塞,那麼,
*
它將接收到一個中斷異常(InterruptedException),從而提早地終結被阻塞狀態。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.