Java線程中斷
線程中斷:
首先線程在未正常結束之前,被強制終止是很危險的事,會造成意想不到的後果。
但有時想讓一個線程結束,或者結束某種等待的狀態,該咋辦?
使用等待/通知機制或者給那個線程一個中斷信號,讓它自己決定該怎麽辦?
中斷使用的場景:
1.線程為了等待一些特定的資源的到來,調用了Thread.sleep(10000), 讓自己10秒後醒過來,但是如果這些特定條件提前到來,來通知處於sleep狀態的線程,“嘿老兄,別再睡了”。
2.線程通過調用子線程的join方法阻塞自己等待子線程結束,但是子線程運行過程中發現自己在短時間內沒法結束,所以它要通知主線程,別再等待子線程了。
這些情況下,就需要中斷。
中斷的函數:
Thread.interrupt()方法來做的。
比如A線程調用了這個方法,這個方法就修改了A線程的中斷狀態。
在非阻塞的線程中
這個方法修改中斷狀態只是改變了線程中的一個布爾變量的值,在線程體run()方法中調用Thread.CurrendThread().isInterrupt()這個方法,會返回一個true。
在可取消阻塞狀態的線程中,比如線程run()方法內調用了Thread.sleep()、Thread.join()、Object.wait()這些方法的線程處於等待的過程中。這個線程調用了interrupt()方法,然後這個線程的Thread.CurrendThread().isInterrupt()
非阻塞狀態的線程中:
public class Interrupt { public static void main(String[] args) { // Interrupt interrupt=new Interrupt(); ThreadC threadC=new ThreadC(); threadC.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } threadC.interrupt(); } } class ThreadC extends Thread{ public void run(){ while(true){ if (Thread.currentThread().isInterrupted()){ System.out.println("Someone interrupt me"); }else{ System.out.println("Thread is Going ..."); } } } }
運行結果:
結果分析:
main方法中線程threadC 開始執行,threadC線程此時沒有被中斷,不斷輸出 Thread is Going。
在main線程睡眠3秒結束後,執行了threadC.interrupt()方法,中斷線程,此時Thread.currentThread().isInterrupted()的值成為了true。但是線程卻不會停止,會不斷的輸出Someone interrupt me,它只是被修改了一個中斷信號。
當在main方法中調用threadC.interrupt()方法的時候,線程threadC的中斷狀態(interrupted status )會被置位,然後在線程體內通過Thread.currentThread().isInterrupted()來檢查這個布爾變量的中斷狀態。
阻塞狀態的線程:
public class Interrupt { public static void ThreadD threadD=new ThreadD(); threadD.start(); System.out.println("線程開始執行"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("中斷線程"); threadD.interrupt(); } } class ThreadD extends Thread{ boolean stop=false; public void run(){ // while(!stop){ // System.out.println("Thread is Going ..."); // } try { Thread.sleep(3000); } catch (InterruptedException e) { System.out.println("線程睡眠被中斷"); } System.out.println("線程繼續執行..."); } } main(String[] args) {
運行結果:
結果分析:
如果線程被Object.warit()、Thread.sleep()、Thread.join()方法阻塞,調用該線程的interrupt()方法的時候會 拋出InterruptException異常,從而提早的結束阻塞狀態。
線程睡眠3秒,main方法睡眠2秒後執行threadD.interrupt()方法。此時線程會拋出異常,結束睡眠。
其它:
不是所有阻塞方法收到中斷後都可以取消阻塞狀態,輸入和輸出類會阻塞等待IO完成,但是它們不會拋出interruptedException,而且在被中斷的時候也不會退出阻塞狀態。
synchronized在獲鎖的過程中是不能被中斷的。
但是 ReentrantLock 支持可中斷的獲取模式即 tryLock(long time, TimeUnit unit)。
Java線程中斷