線程中斷到底是什么
提示:更多優秀博文請移步博主的GitHub倉庫:GitHub學習筆記、Gitee學習筆記
我們如何讓線程安全的停止呢?
1. 線程自然終止
自然執行完或拋出未處理異常。
2. stop(),resume(),suspend()方法
stop(),resume(),suspend()已不建議使用,stop()會導致線程不會正確釋放資源,suspend()容易導致死鎖。
- 停止多線程:
public void stop(); - 銷毀多線程:
public void destory(); - 掛起線程:
public final void suspend(); 暫停執行 - 恢復掛起的線程執行:
public final void resume();
3. 線程中斷
Thread類提供了interrupt方法,用于中斷目標線程的執行。
3.1 interrupt方法
interrupt()方法用于中斷一個線程,而Java中線程的處理是協作式的而不是搶占式的。所謂協作式的意思是:實際上調用一個線程的interrupt() 方法中斷一個線程,并不是強行關閉這個線程,只是跟這個線程打個招呼,將線程的中斷標志位置為true,線程是否中斷,由線程本身決定。
public class UserRunnable implements Runnable {
@Override
public void run() {
while (true){
System.out.println(Thread.currentThread().getName()+"is running");
}
}
}
public class SafeExitTest {
public static void main(String[] args) {
Thread thread = new Thread(new UserRunnable());
thread.start();
thread.interrupt();
}
}
我們可以看到,在UserRunnable線程中,我們并沒有對中斷進行任何處理,所以在SafeExitTest中調用線程的interrupt方法并不會導致線程的中斷,控制臺還是會繼續打印。只有在目標線程中進行了正確的中斷處理后才會有中斷效果:
public class UserRunnable implements Runnable {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {//判斷當前線程是否被中斷
System.out.println(Thread.currentThread().getName() + "is running");
}
}
}
Thread類中相關方法
- isInterrupted() :判定指定線程是否處于中斷狀態。
- static interrupted() :靜態方法,判定當前線程是否處于中斷狀態,同時將中斷標志位改為false。
3.2 阻塞線程與線程中斷
Java中斷響應是描述當一個線程或方法A處于運行、阻塞或死鎖狀態時,外界(通常指其他線程、系統IO等)對A的影響能否讓A線程或者方法拋出InterruptedException異常并提前返回,如果會提前返回并且拋出InterruptedException,就叫可中斷響應方法或線程,如果不會拋出InterruptedException,就叫不可中斷線程或方法。
Java語言中所有阻塞方法都聲明拋出InterruptedException異常(例如 Thread.sleep()、 Thread.join() 或 Object.wait())。也就是說,如果一個線程執行了阻塞方法,使得當前線阻塞,第三方線程執行interrupt方法中斷線程,都會使得該阻塞方法拋出InterruptedException異常并退出阻塞,并且將當前線程的中斷標志位設置為false。
如果沒有這個機制, interrupt() 則只是單純設置線程的中斷狀態。那這個試圖中斷的線程仍在阻塞當中,那么后序的中斷工作則無法進行。
3.3 阻塞線程的線程中斷案例
public class UserRunnable implements Runnable {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
System.out.println(Thread.currentThread().getName() + "is running");
try {
Thread.sleep(10);//第7行
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class SafeExitTest {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new UserRunnable());
thread.start();
Thread.sleep(10);
thread.interrupt();//第6行
}
}
上面的代碼我們僅僅是在每次循環的時候讓線程sleep了10ms,但這很有可能會導致中斷操作的失敗(注意這里說的是很有可能)。

可以看到控制臺不斷輸出"Thread-0is running",這是因為在執行SafeExitTest:6(SafeExitTest類的第6行代碼)這行代碼時,目標線程處于阻塞狀態,此時UserRunnable:7這行代碼拋出InterruptedException異常,線程退出阻塞狀態,并將中斷標志位設置為false。這也就是為什么雖然在while語句中對中斷標志位進行了判斷,而在主線程試圖中斷目標線程時,目標線程仍能繼續循環的原因。
經過多次測試也會出現中斷成功的情況:

出現這種情況,是因為中斷操作放生在第一次循環完成和第二次循環判斷開始之前。
具體細節參考:
https://blog.csdn.net/meiliangdeng1990/article/details/80559012
https://www.ibm.com/developerworks/cn/java/j-jtp05236.html

浙公網安備 33010602011771號