interrupt interrupted isInterrupted 是三個「長相」很是相似的方法。
本文將對這三個方法簡單的對比下,首先了解下線程中止的方式
線程中止方式
在Java中若是想中止一個線程,有三種方法
- 採用退出標誌,使得run方法執行完以後線程天然終止
- 使用stop強行終止線程,但該方法因爲安全問題已經被deprecated
- 使用中斷機制
退出標誌
public class T9 extends Thread {
private boolean running;
public void setRunning(boolean running) {
this.running = running;
}
@Override
public void run() {
while (running){
System.out.println("i am working ....");
}
}
public static void main(String[] args) {
T9 myThread = new T9();
myThread.setRunning(true);
myThread.start();
try {
TimeUnit.MILLISECONDS.sleep(2);
} catch (Exception e) {
}
myThread.setRunning(false);
}
}
運行幾回,結果略有不一樣
stop 棄用
public class T9 extends Thread {
private boolean running;
public void setRunning(boolean running) {
this.running = running;
}
@Override
public void run() {
while (running) {
System.out.println("i am working ....");
}
}
public static void main(String[] args) {
T9 myThread = new T9();
myThread.setRunning(true);
myThread.start();
try {
TimeUnit.MILLISECONDS.sleep(2);
} catch (Exception e) {
}
myThread.stop();
}
}
中斷機制
stop等方法已經棄用,退出標記不夠靈活有時也有問題,因此目前最合適的解決方式是藉助於中斷機制
中斷機制是一種處理邏輯,而不是說當即中斷
中斷機制是一種「請求---處理」模型,是一種軟中斷,並不會由於中斷的設置當即中止運行
中斷機制的邏輯藉助於「中斷標誌」,當請求一個線程中斷時,能夠經過設置目標線程的中斷標誌位進行操做
簡單的邏輯以下圖所示:
因此說,對於線程的中止的三種方式,中斷機制是一種更好的方式,並且也是一種更加友好的方式。
public class T9 extends Thread { private boolean running; public void setRunning(boolean running) { this.running = running; } @Override public void run() { while (running) { System.out.println("i am working ...."); } } public static void main(String[] args) { T9 myThread = new T9(); myThread.setRunning(true); myThread.start(); myThread.interrupt(); } }
上面的代碼中,儘管咱們經過myThread.interrupt();設置了標誌位,可是線程仍舊繼續運行,徹底並無中止的意思
public class T9 extends Thread {
private boolean running;
public void setRunning(boolean running) {
this.running = running;
}
@Override
public void run() {
while (running) {
if (Thread.currentThread().isInterrupted()) {
break;
}
System.out.println("i am working ....");
}
}
public static void main(String[] args) {
T9 myThread = new T9();
myThread.setRunning(true);
myThread.start();
try {
TimeUnit.MILLISECONDS.sleep(2);
} catch (Exception e) {
}
myThread.interrupt();
}
}
上面代碼中,在run方法中判斷中斷標誌位,若是發現中斷標誌被置位,那麼break,也就是跳出循環
主函數中,線程啓動後,主線程休眠2毫秒而後將myThread中斷,程序運行一段時間後終止運行
因此能夠看得出來,藉助於中斷機制對一個線程進行處理,進行中斷標誌置位,並不會對線程的運行產生影響,到底有何影響,重點要看到底你面對中斷標誌位會作什麼處理。
中斷標誌位
經過上面的分析,咱們能夠很清楚的看得出來,中斷機制的核心就是藉助於中斷標誌位
而 interrupt interrupted isInterrupted三個方法其實就是對於中斷標誌位的操做
從新審視下方法,兩個實例方法一個靜態方法
API文檔
public void interrupt()
中斷一個線程(設置標誌位)
除非是當前線程正在中斷本身(這在任何狀況下都是容許的),不然該線程的 checkAccess 方法就會被調用,這可能拋出 SecurityException。
若是線程在調用 Object 類的 wait()、wait(long) 或 wait(long, int) 方法,或者該類的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法過程當中受阻,則其中斷狀態將被清除,它還將收到一個 InterruptedException。
若是該線程在可中斷的通道上的 I/O 操做中受阻,則該通道將被關閉,該線程的中斷狀態將被設置而且該線程將收到一個 ClosedByInterruptException。
若是該線程在一個 Selector 中受阻,則該線程的中斷狀態將被設置,它將當即從選擇操做返回,並可能帶有一個非零值,就好像調用了選擇器的 wakeup 方法同樣。
若是之前的條件都沒有保存,則該線程的中斷狀態將被設置。
中斷一個不處於活動狀態的線程不須要任何做用。
拋出:
SecurityException - 若是當前線程沒法修改該線程
注意:
若是不是線程本身在中斷本身的話,會有安全管理器先進行校驗,若是權限不夠,將會拋出SecurityException
若是位於特殊的等待狀態,好比調用wait()、wait(long)或者join()或者sleep()等方法,中斷標誌位將會被清除,而且收到一個InterruptedException
前面說到中斷標誌被置位不影響線程的正常運行,可是這個InterruptedException又是什麼意思?
中斷標誌的確是不影響線程的運行,要看線程對於中斷標誌是如何進行處理的
可是若是處於等待的話,就會拋出異常
簡單說,當一個線程正常運行的時候,能夠不用搭理中斷標誌位;
可是若是好比在等人,在睡覺,一旦被中斷就會被吵醒,吵醒了、不爽了、天然要發發牢騷,這個牢騷就是InterruptedException
public boolean isInterrupted()
測試線程是否已經中斷
線程的中斷狀態不受該方法的影響
A thread interruption ignored because a thread was not alive at the time of the interrupt will be reflected by this method returning false.
在中斷髮生時,若是一個線程並非alive的,中斷操做將會被忽略,也會經過這個方法返回false反映出來
返回:
若是該線程已經中斷,則返回 true;不然返回 false。
若是一個線程根本都不是alive的,調用這個方法也是返回false
public static boolean interrupted()
測試當前線程是否已經中斷。
線程的中斷狀態 由該方法清除。
換句話說,若是連續兩次調用該方法,則第二次調用將返回 false(在第一次調用已清除了其中斷狀態以後,且第二次調用檢驗完中斷狀態前,當前線程再次中斷的狀況除外)。
在中斷髮生時,若是一個線程並非alive的,中斷操做將會被忽略,也會經過這個方法返回false反映出來
A thread interruption ignored because a thread was not alive at the time of the interrupt will be reflected by this method returning false.
返回:
若是當前線程已經中斷,則返回 true;不然返回 false。
接下來看一個方法
測試線程是否被中斷。
中斷標誌位將會根據參數ClearInterrupted的值決定是否會被清除
這是一個實例方法,因此須要依賴於某個實例對象
再仔細看看靜態方法interrupted
內部藉助於上面的那個私有方法
他的含義就是,測試當前線程是否被中斷,而且清除中斷標誌位
而對於實例方法isInterrupted,仍舊是藉助於本地方法,測試某個線程是否被中斷,可是並不會清除線程的中斷標誌
小結
三個方法全都是用來對線程中斷標誌進行操做的
public void interrupt()、public boolean isInterrupted()做爲實例方法,是對指定線程的操做
假設中斷標誌位interruptState
那麼對於interrupt來講至關於set方法
public void setInterruptState(boolean interruptState) {
this.interruptState = interruptState;
}
對於isInterrupted來講,至關於get方法
public boolean isInterruptState() {
return interruptState;
}
而對於interrupted() 則是至關於getter and setter,而且,是針對於當前線程的
總結
對於三個方法interrupt interrupted isInterrupted,重點是要了解中斷標誌位
從getter和setter方法的角度理解的話,可以更好地理解,從方法名中也能夠很好地看得出來
interrupt做爲動詞,因此是使之中斷,天然是setter方法
而對於isInterrupted 典型的疑問句式,因此是對中斷標誌位的測試 是getter方法
interrupted看起來就奇葩了一點,因此他是set和get ,而且是針對當前線程的
這樣的話就不會混淆了,畢竟名字的確是有些接近