Thread.interrupt()方法理解
多線程編程?
不客氣地說(shuō),至少有一半人認(rèn)為,線程的”中斷”就是讓線程停止。
如果你也這么認(rèn)為,那你對(duì)多線程編程還沒(méi)有入門。
在java中,線程的中斷(interrupt)只是改變了線程的中斷狀態(tài),至于這個(gè)中斷狀態(tài)改變后帶來(lái)的結(jié)果,那是無(wú)法確定的,有時(shí)它更是讓停止中的線程繼續(xù)執(zhí)行的唯一手段。不但不是讓線程停止運(yùn)行,反而是繼續(xù)執(zhí)行線程的手段。
對(duì)于執(zhí)行一般邏輯的線程,如果調(diào)用它的interrupt()方法,那么對(duì)這個(gè)線程沒(méi)有任何
影響,比如線程a正在執(zhí)行:
while(條件) x ++;
這樣的語(yǔ)句,如果其它線程調(diào)用a.interrupt();那么并不會(huì)影響a對(duì)象上運(yùn)行的線程,但中斷標(biāo)志會(huì)變?yōu)閠rue。如果在其它線程里再次測(cè)試a的中斷狀態(tài),則中斷標(biāo)志為true,但并不會(huì)停止這個(gè)線程的運(yùn)行。
在一個(gè)線程對(duì)象上調(diào)用interrupt()方法,真正有影響的是wait,join,sleep方法,當(dāng)然這三個(gè)方法包括它們的重載方法。
請(qǐng)注意:[上面這三個(gè)方法都會(huì)拋出InterruptedException],記住這句話,下面我會(huì)重復(fù)。一個(gè)線程在調(diào)用interrupt()后,自己不會(huì)拋出InterruptedException異常,所以你看到interrupt()并沒(méi)有拋出這個(gè)異常,所以我上面說(shuō)如果線程a正在執(zhí)行while(條件) x ++;你調(diào)用a.interrupt()后線程會(huì)繼續(xù)正常地執(zhí)行下去.
附:
Thread.sleep()源碼:
- 1
Object.wait()源碼:
public final native void wait(long timeout) throws InterruptedException;- 1
Thread.join()源碼
public final synchronized void join(long millis) throws InterruptedException {... }- 1
- 2
- 3
但是,如果一個(gè)線程被調(diào)用了interrupt()后,它的狀態(tài)是阻塞狀態(tài)的。而且這個(gè)狀態(tài)是由于正在執(zhí)行wait,join,sleep的線程導(dǎo)致的,那么是會(huì)改變線程的運(yùn)行結(jié)果.
一. 對(duì)于wait中的等待notify、notifyAll換新的線程,其實(shí)這個(gè)線程已經(jīng)“暫停”執(zhí)行,因?yàn)樗谀骋粚?duì)象的休息室中,這時(shí)如果它的中斷狀態(tài)被改變,那么它就會(huì)拋出異常。這個(gè)InterruptedException異常不是線程拋出的,而是wait方法,也就是對(duì)象的wait方法內(nèi)部會(huì)不斷檢查在此對(duì)象上休息的線程的狀態(tài),如果發(fā)現(xiàn)哪個(gè)線程的狀態(tài)被置為已中斷,則會(huì)拋出InterruptedException,意思就是這個(gè)線程不能再等待了,其意義就等同于喚醒它了,然后執(zhí)行catch中的代碼。
這里唯一的區(qū)別是,被nortify/All喚醒的線程會(huì)繼續(xù)執(zhí)行wait下面的語(yǔ)句,而在wait
中被中斷的線程則將控制權(quán)交給了catch語(yǔ)句。一些正常的邏輯要被放到catch中來(lái)運(yùn)行。但有時(shí)這是唯一手段,比如一個(gè)線程a在某一對(duì)象b的wait中等待喚醒,其它線程必須獲取到對(duì)象b的監(jiān)視鎖才能調(diào)用b.notify()[All],否則你就無(wú)法喚醒線程a,但在任何線程中可以無(wú)條件地調(diào)用a.interrupt();喚醒后的邏輯你要放在catch中,當(dāng)然同notify/All一樣,繼續(xù)執(zhí)行a線程的條件還是要等拿到b對(duì)象的監(jiān)視鎖。
二. 對(duì)于sleep中的線程,如果你調(diào)用了Thread.sleep(一年);現(xiàn)在你后悔了,想讓它早
些醒過(guò)來(lái),調(diào)用interrupt()方法就是唯一手段,只有改變它的中斷狀態(tài),讓它從sleep中將控制權(quán)轉(zhuǎn)到處理異常的catch語(yǔ)句中,然后再由catch中的處理轉(zhuǎn)換到正常的邏輯。同樣,對(duì)于join中的線程你也可以這樣處理。
對(duì)于一般介紹多線程模式的書上,他們會(huì)這樣來(lái)介紹:當(dāng)一個(gè)線程被中斷后,在進(jìn)入wait,sleep,join方法時(shí)會(huì)拋出異常。是的,這一點(diǎn)也沒(méi)有錯(cuò),但是這有什么意義呢?如果你知道那個(gè)線程的狀態(tài)已經(jīng)處于中斷狀態(tài),為什么還要讓它進(jìn)入這三個(gè)方法呢?當(dāng)然有時(shí)是必須這么做的,但大多數(shù)時(shí)候沒(méi)有這么做的理由,所以我上面主要介紹了在已經(jīng)調(diào)用這三個(gè)方法的線程上調(diào)用interrupt()方法讓它從這幾個(gè)方法的”暫停”狀態(tài)中恢復(fù)過(guò)來(lái)。這個(gè)恢復(fù)過(guò)來(lái)就可以包含兩個(gè)目的:
一. [可以使線程繼續(xù)執(zhí)行],那就是在catch語(yǔ)句中執(zhí)行醒來(lái)后的邏輯,或由catch語(yǔ)句
轉(zhuǎn)回正常的邏輯。總之它是從wait,sleep,join的暫停狀態(tài)活過(guò)來(lái)了。
二. [可以直接停止線程的運(yùn)行],當(dāng)然在catch中什么也不處理,或return,那么就完成了當(dāng)前線程的使命,可以使在上面”暫停”的狀態(tài)中立即真正的”停止”。
總結(jié)
以上是生活随笔為你收集整理的Thread.interrupt()方法理解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Windows批处理命令学习
- 下一篇: 块编码、对象编码、小波编码、分布式编码【