1. 程式人生 > >java 併發 之 Interrupt()

java 併發 之 Interrupt()

interrupt簡述

interrupt() 方法只是改變中斷狀態而已,它不會中斷一個正在執行的執行緒。這一方法實際完成的是,給受阻塞的執行緒發出一箇中斷訊號,這樣受阻執行緒就得以退出阻塞的狀態。 更確切的說,如果執行緒被Object.wait, Thread.join和Thread.sleep三種方法之一阻塞,此時呼叫該執行緒的interrupt()方法,那麼該執行緒將丟擲一個 InterruptedException中斷異常(該執行緒必須事先預備好處理此異常),從而提早地終結被阻塞狀態。如果執行緒沒有被阻塞,這時呼叫 interrupt()將不起作用,直到執行到wait(),sleep(),join()時,才馬上會丟擲 InterruptedException。

線 程A在執行sleep,wait,join時,執行緒B呼叫執行緒A的interrupt方法,的確這一個時候A會有 InterruptedException 異常丟擲來。但這其實是在sleep,wait,join這些方法內部會不斷檢查中斷狀態的值,而自己丟擲的InterruptedException。 如果執行緒A正在執行一些指定的操作時如值,for,while,if,呼叫方法等,不會去檢查中斷狀態,則執行緒A不會丟擲 InterruptedException,而會一直執行著自己的操作。

注意:

當執行緒A執行到wait(),sleep(),join()時,丟擲InterruptedException後,中斷狀態已經被系統復位了,執行緒A呼叫Thread.interrupted()返回的是false。

如果執行緒被呼叫了interrupt(),此時該執行緒並不在wait(),sleep(),join()時,下次執行wait(),sleep(),join()時,一樣會丟擲InterruptedException,當然丟擲後該執行緒的中斷狀態也會被系統復位。

(總結一下:呼叫interrupt()方法,立刻改變的是中斷狀態,但如果不是在阻塞態,就不會丟擲異常;如果在進入阻塞態後,中斷狀態為已中斷,就會立刻丟擲異常)

  1. sleep() &interrupt()

執行緒A正在使用sleep()暫停著: Thread.sleep(100000),如果要取消它的等待狀態,可以在正在執行的執行緒裡(比如這裡是B)呼叫a.interrupt()[a是執行緒A對應到的Thread例項],令執行緒A放棄睡眠操作。即,線上程B中執行a.interrupt(),處於阻塞中的執行緒a將放棄睡眠操作。

當在sleep中時執行緒被呼叫interrupt()時,就馬上會放棄暫停的狀態並丟擲InterruptedException。丟擲異常的,是A執行緒。

  1. wait() &interrupt()

執行緒A呼叫了wait()進入了等待狀態,也可以用interrupt()取消。不過這時候要注意鎖定的問題。執行緒在進入等待區,會把鎖定解除,當對等待中的執行緒呼叫interrupt()時,會先重新獲取鎖定,再丟擲異常。在獲取鎖定之前,是無法丟擲異常的。

  1. join() &interrupt()

當執行緒以join()等待其他執行緒結束時,當它被呼叫interrupt(),它與sleep()時一樣,會馬上跳到catch塊裡.。

注意,呼叫的interrupt()方法,一定是呼叫被阻塞執行緒的interrupt方法。如線上程a中呼叫執行緒t.interrupt()。