總結一下interrupt,interrupted isInterrupted的區別
interrupt()
的作用是中斷本執行緒。
本執行緒中斷自己是被允許的;其它執行緒呼叫本執行緒的interrupt()
方法時,會通過checkAccess()
檢查許可權。這有可能丟擲SecurityException
異常。
如果本執行緒是處於阻塞狀態:呼叫執行緒的wait(), wait(long)或wait(long, int)
會讓它進入等待(阻塞)狀態,或者呼叫執行緒的join(), join(long), join(long, int), sleep(long), sleep(long, int)
也會讓它進入阻塞狀態。若執行緒在阻塞狀態時,呼叫了它的interrupt()
方法,那麼它的“中斷狀態”會被清除並且會收到一個InterruptedException
異常。例如,執行緒通過wait()
進入阻塞狀態,此時通過interrupt()
中斷該執行緒;呼叫interrupt()
會立即將執行緒的中斷標記設為“true”,但是由於執行緒處於阻塞狀態,所以該“中斷標記”會立即被清除為“false”,同時,會產生一個InterruptedException
的異常。
如果執行緒被阻塞在一個Selector選擇器中,那麼通過interrupt()
中斷它時;執行緒的中斷標記會被設定為true,並且它會立即從選擇操作中返回。
如果不屬於前面所說的情況,那麼通過interrupt()中斷執行緒時,它的中斷標記會被設定為“true”。
中斷一個“已終止的執行緒”不會產生任何操作。
interrupted()
和isInterrupted()
的區別
interrupted() 和 isInterrupted()都能夠用於檢測物件的“中斷標記”。
區別是,interrupted()除了返回中斷標記之外,它還會清除中斷標記(即將中斷標記設為false);
而isInterrupted()僅僅返回中斷標記。
標準的中斷寫法如下所示(中斷阻塞的執行緒和未阻塞的執行緒)
終止執行緒的方式
Thread中的stop()和suspend()方法,由於固有的不安全性,已經建議不再使用!
下面,我先分別討論執行緒在“阻塞狀態”和“執行狀態”的終止方式,然後再總結出一個通用的方式。
1 終止處於“阻塞狀態”的執行緒
通常,我們通過“中斷”方式終止處於“阻塞狀態”的執行緒。
當執行緒由於被呼叫了sleep(), wait(), join()等方法而進入阻塞狀態;若此時呼叫執行緒的interrupt()將執行緒的中斷標記設為true。由於處於阻塞狀態,中斷標記會被清除,同時產生一個InterruptedException異常。將InterruptedException放在適當的為止就能終止執行緒,形式如下:
@Override
public void run() {
try {
while (true) {
// 執行任務...
}
} catch (InterruptedException ie) {
// 由於產生InterruptedException異常,退出while(true)迴圈,執行緒終止!
}
}
說明:在while(true)中不斷的執行任務,當執行緒處於阻塞狀態時,呼叫執行緒的interrupt()產生InterruptedException中斷。中斷的捕獲在while(true)之外,這樣就退出了while(true)迴圈!
注意:對InterruptedException的捕獲務一般放在while(true)迴圈體的外面,這樣,在產生異常時就退出了while(true)迴圈。否則,InterruptedException在while(true)迴圈體之內,就需要額外的新增退出處理。形式如下:
@Override
public void run() {
while (true) {
try {
// 執行任務...
} catch (InterruptedException ie) {
// InterruptedException在while(true)迴圈體內。
// 當執行緒產生了InterruptedException異常時,while(true)仍能繼續執行!需要手動退出
break;
}
}
}
說明:上面的InterruptedException異常的捕獲在whle(true)之內。當產生InterruptedException異常時,被catch處理之外,仍然在while(true)迴圈體內;要退出while(true)迴圈體,需要額外的執行退出while(true)的操作。
2 終止處於“執行狀態”的執行緒
通常,我們通過“標記”方式終止處於“執行狀態”的執行緒。其中,包括“中斷標記”和“額外新增標記”。
(01) 通過“中斷標記”終止執行緒。
形式如下:
@Override
public void run() {
while (!isInterrupted()) {
// 執行任務...
}
}
說明:isInterrupted()是判斷執行緒的中斷標記是不是為true。當執行緒處於執行狀態,並且我們需要終止它時;可以呼叫執行緒的interrupt()方法,使用執行緒的中斷標記為true,即isInterrupted()會返回true。此時,就會退出while迴圈。
注意:interrupt()並不會終止處於“執行狀態”的執行緒!它會將執行緒的中斷標記設為true。
(02) 通過“額外新增標記”。
形式如下:
private volatile boolean flag= true;
protected void stopTask() {
flag = false;
}
@Override
public void run() {
while (flag) {
// 執行任務...
}
}
說明:執行緒中有一個flag標記,它的預設值是true;並且我們提供stopTask()來設定flag標記。當我們需要終止該執行緒時,呼叫該執行緒的stopTask()方法就可以讓執行緒退出while迴圈。
注意:將flag定義為volatile型別,是為了保證flag的可見性。即其它執行緒通過stopTask()修改了flag之後,本執行緒能看到修改後的flag的值。
綜合執行緒處於“阻塞狀態”和“執行狀態”的終止方式,比較通用的終止執行緒的形式如下:
@Override
public void run() {
try {
// 1. isInterrupted()保證,只要中斷標記為true就終止執行緒。
while (!isInterrupted()) {
// 執行任務...
}
} catch (InterruptedException ie) {
// 2. InterruptedException異常保證,當InterruptedException異常產生時,執行緒被終止。
}
}