轉發請聲明出處:http://blog.csdn.net/qq_24692041/article/details/78455131
線程中斷,interrupt方法
先看代碼和輸出結果
子線程代碼:
package com.example; /** * Created by PICO-USER on 2017/11/6. */ public class ThreadA extends Thread { @Override public void run() { super.run(); try{ System.out.println("in ThreadA - about to sleep for 20 seconds :"+isInterrupted()); Thread.sleep(20000); System.out.println("in ThreadA - wake up"); }catch(InterruptedException e){ System.out.println("in ThreadA - interrupted while sleeping"); System.out.println("in ThreadA - interrupt status of threadA :"+isInterrupted()); //處理完中斷異常後,返回到run()方法人口, //如果沒有return,線程不會實際被中斷,它會繼續打印下面的信息 // return; } System.out.println("in ThreadA - leaving normally"); } }
主線程代碼:
package com.example; public class MyClass { public static void main(String[] args0) throws InterruptedException { ThreadA threadA = new ThreadA(); threadA.start(); //主線程休眠2秒,從而確保剛纔啓動的線程有機會執行一段時間 try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("in main() - interrupting other thread"); //中斷線程t threadA.interrupt(); System.out.println("in main() - interrupt status of threadA :"+threadA.isInterrupted()); System.out.println("in main() - leaving"); } }輸出結果:
代碼和結果分析:
主程序中先啓動了線程A,此時線程A的run方法開始執行,打印完“in run() - about to sleep for 20 seconds”之後A進入休眠狀態,休眠20秒。此時主線程是在併發執行的,主線程休眠2秒,2秒過後主線程休眠結束,調用interrupt方法中斷A線程,並且主線程main方法執行完畢,所以主線程消亡。此時A線程本應該還在休眠狀態,但由於interrupt方法被調用,直接讓A線程結束了休眠狀態拋出了中斷異常,然後繼續執行try,catch後面的代碼,run方法走完之後消亡。這裏注意:如果在catch塊中return,那後面的代碼將不會繼續執行,因爲return代表run方法執行結束,A線程就直接消亡了。
重點:從上面的代碼可以看出interrupt方法的調用只是在目標線程中設置了中斷標誌爲true,代表該線程已經被中斷,並不會直接終止該線程。注意看isInterrupt方法打印出來的結果,在A線程開始執行run方法的時候打印的是false,然後中斷A線程的一瞬間我們在主線程打印了A線程的中斷狀態是true,最後在A線程的catch塊中打印出來的卻是false,說明interrupt方法的調用的時候的確是設置了中斷標誌,並且沒有直接終止線程的執行。
當線程遇到阻塞,比如調用sleep,wait,join方法的時候,就會拋出中斷異常,並且重置中斷標誌。所以上面catch方法中的isInterrupt方法返回的是false。
最後說一點,其實上面我們在主線程打印A線程中斷標誌的時候有取巧的嫌疑,只是打印的位置哈,interrupt設置中斷標誌的結論肯定是沒錯的。因爲在主線程中打印A的中斷標誌的時候,有可能A的異常已經被拋出,並且重置了中斷標誌,那樣的結果就會是false。
方法判斷線程中斷
線程中斷判斷方法有兩個,一個是interrupted()方法,該方法是靜態方法,該方法是中斷當前線程並且該方法會將中斷標誌重置,另一個方法就是上面用到的isInterrupted()方法,這個方法是非靜態方法,作用於對象,返回的是目標線程的中斷標誌,本身並不會重置中斷標誌,需要線程阻塞,比如調用sleep,wait,join方法導致阻塞的時候,將中斷標誌重置。下面看看兩個示例代碼:
package com.example; /** * Created by PICO-USER on 2017/11/6. */ public class ThreadB extends Thread { @Override public void run() { super.run(); System.out.print("ThreadB isInterrupted :"+isInterrupted()+"\n"); System.out.print("ThreadB interrupted :"+ThreadB.interrupted()+"\n"); interrupt(); System.out.print("ThreadB isInterrupted :"+isInterrupted()+"\n"); System.out.print("ThreadB isInterrupted :"+isInterrupted()+"\n"); System.out.print("ThreadB interrupted :"+ThreadB.interrupted()+"\n"); System.out.print("ThreadB interrupted :"+ThreadB.interrupted()+"\n"); } }
package com.example; public class MyClass { public static void main(String[] args0) throws InterruptedException { ThreadB threadB = new ThreadB(); threadB.start(); System.out.print("main :" + Thread.currentThread().isInterrupted() + "\n"); } }運行結果:
很清楚的看到調用interrupt方法之後連續打印的兩次isInterrupted的返回值都是true,然而第一次調用interrupted方法的返回值是true,但是第二次調用的時候就已經被重置返回false了。