如果一個方法后面有“throws InterruptedException”(即會拋出InterruptedException異常的方法),表示這個方法內(或是這個方法中所調用的方法內),可能會拋出InterruptedException異常。在多線程程序設計中,這通常告訴我們兩點:
- 這是“需要時間”的方法
- 這是“可以取消”的方法
即,如果一個方法后面有“thorws InterruptedException”表示這個方法可能會花點時間,但是可以取消。
Java中會拋出InterruptException異常的有下面三個方法:
- java.lang.Object類(及其子類)實例的wait方法
- java.lang.Object類(及其子類)實例的sleep方法
- java.lang.Thread類(及其子類)實例的join方法
根據上面的兩點,首先,這三個方法都是需要花點時間的方法,這個很好理解。其次,他么都可以被取消,具體怎么取消,下面分別說明。
取消wait
可以調用interrupt方法(這個方法是java.lang.Thread類(及其子類)實例的方法,某個線程都可以在任何時候調用其他線程的interrupt方法)來取消wait方法的等待。即不用再等待notify/notifyAll方法的“通知”了。當對某個wait的線程調用interrupt方法的時候,這個線程會從wait set中出來,先重新獲得鎖定,再拋出InterruptedException。注意,在獲得鎖定前,是不會拋出InterruptedException異常的。
為了加深理解,這里對比一下notify/notifyAll方法和interrupt方法。首先,notify/notifyAll方法是java.lang.Object類(及其子類)實例的方法,而interrupt方法是java.lang.Thread類(及其子類)實例的方法。其次,notify/notifyAll方法調用時需要獲得鎖定,而interrupt方法不用,如前所述,interrupt方法可以在任何時候被調用。最后,被notify/notifyAll方法喚醒的線程是(重新獲得鎖定后)繼續執行wait方法之后的方法,而被interrupt方法喚醒的線程則滿足前面所的第二條“可以被取消”,即讓被喚醒的線程(重新獲得鎖定后)在wait方法上拋出InterruptedException。
取消sleep
當sleep中的線程被調用interrupt方法時,會馬上(不用想取消wait一樣,還要獲得鎖定)放棄sleep狀態,并拋出InterruptedException異常。
取消join
當線程以join方法等待其他線程結束時,可以被調用interrupt方法來馬上取消等待其他線程結束。
下面是關于java內部是怎么實現取消上面三個方法的等待的。在線程內部,有一個標志位表示線程的中斷狀態。有兩個方法可以設置這個狀態,interrupt方法和interrupted方法,interrupted方法屬于java.lang.Thread類(及其子類)的靜態方法,用來返回
當前線程的中斷狀態,并清除這個狀態。調用interrupt方法將設置此標志位(表示讓被調用線程處于中斷狀態),調用interrupted方法返回值是當前線程是否被中斷,并取消此標志位(表示讓當前線程處于非中斷狀態)。在實現細節上,會拋出InterruptedException異常的sleep,wait和join方法在內部不斷的檢測這個中斷狀態,如果發現被設置了,則拋出InterruptedException異常。java.lang.Thread類(及其子類)實例還有一個isInterrupted方法來檢測這個標志位,如果被設置了返回true,否則返回false。還需要進一步補充的是:interrupt方法和interrupted方法的區別。可以對任意的一個線程調用interrupt方法,但是只能對當前的線程(即正在運行的線程)調用interrupted方法(此方法是靜態方法),所以,在程序中無法清除其他線程的中斷狀態了。
參考:
《Java多線程設計模式》,中國鐵道出版社,2005,結城浩
文章來源:
http://localhost/wp2/?p=99