3 回答

TA貢獻1815條經驗 獲得超13個贊
這是因為中斷標志如何為線程工作。
當您中斷一個線程時,基本上只會發生一件事:設置中斷標志,僅此而已。然后取決于該線程正在運行的代碼是否確實執行了操作。
一般的想法是,如果可以的話,你會中止你正在做的事情并拋出一些合理的異常。
java 內置的一些方法保證這正是它們的工作方式。您可以輕松識別它們:它們都被聲明為 throw InterruptedException。有許多方法在中斷時故意未定義行為(這取決于操作系統):所有那些阻塞 I/O 方法都是這樣的。如果您處于阻塞網絡讀取中并且中斷讀取時阻塞的線程,則可能會導致讀取調用時出現 IOException,或者.. 不會。
更重要的是,當“處理”中斷時(中止+拋出異常正在處理它!),標志被清除。
請注意,如果您使用檢查標志的標準方法(即Thread.interrupted(). 這個方法檢查你自己線程的中斷標志并清除它。if使用這個:你已經寫了一個聲明或諸如此類的東西來處理中斷這一事實意味著你已經處理了它。
因此,如果您只想返回以響應被打斷,正確的代碼是:
Runnable task = () -> {
while (!Thread.interrupted()) {
System.out.println("Executing");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
return;
}
}
};
無論中斷何時發生,此方法都會退出。在 99.99% 的情況下,它會在阻塞睡眠時發生。然后標志將為假,并拋出異常。在不太可能發生的情況下,它會在其外部處理時發生,而 while 條件將拾取它。
請注意,如果您提高了中斷標志并調用了類似的方法Thread.sleep,該方法將通過清除標志并拋出來立即InterruptedException完成執行。不管中斷發生在哪里,上面的例子都會做同樣的事情(靜默退出run方法,中斷標志將被清除)。

TA貢獻1839條經驗 獲得超15個贊
InterruptedException并且Thread.isInterrupted()實際上非常獨立。sleep()當您在長時間運行的循環中使用時,會引入并發癥。你sleep(5000)實際上是清除你的isInterrupted標志并拋出InterruptedException.
如果您嘗試以下操作,您會發現線程實際上沒有InterruptException拋出。interrupt()
@Override public void run() {
int b = 0;
while (true) {
if (b++ == 0) System.out.println("running...");
}
}
教訓是,您確實需要同時檢查異常和標志,但它們不應該相互依賴。例如,您的示例捕獲異常,但依賴標志退出循環。如您所見,這是行不通的。
您要么需要break在異常被捕獲時退出 while 循環,要么在循環try/catch 之外(確保捕獲異常使您脫離循環)。
因此,應提供以下任一服務:
while (!Thread.currentThread().isInterrupted()) { // out of the loop when flag is raised
try {
//......
}
catch (InterruptedException e) {
break;//exit loop when exception thrown
}
}
// Or:
try {
while (!Thread.currentThread().isInterrupted()) { // exit loop when flag is raised
//.....
}
}
catch (InterruptedException e) {
// no need to break, as we're already outside
}

TA貢獻1895條經驗 獲得超7個贊
這是帶有打印語句的代碼。
public static void interrupted() throws InterruptedException {
Runnable task = () ->
{
while (true && !Thread.currentThread().isInterrupted()) {
System.out.println("task executing");
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
// this prints false.
System.out.println(Thread.currentThread().isInterrupted());
}
}
};
一旦處理完中斷狀態,線程就不再被認為處于中斷狀態,因此循環繼續。
添加回答
舉報