Java併發(3) 中斷執行緒

2021-06-19 14:45:29 字數 3095 閱讀 4833

2011-03-21 mon | comments

在了解如何中斷執行緒之前,先應該弄清楚執行緒的幾種狀態:

新建狀態(new):乙個新的執行緒在被建立之後,在執行(或阻塞)之前的狀態。

就緒狀態(runnable):當乙個執行緒只要擁有cpu時間片就能執行的時候,這個執行緒就處於就緒狀態。

阻塞狀態(blocked):執行緒還沒有死亡,但是由於一些原因不能繼續執行,但是還能回到就緒狀態。

死亡狀態(dead):當乙個執行緒的任務已經完成,即run方法已經正確返回,或者被中斷,這個執行緒就處於死亡狀態。

引起阻塞的原因

乙個執行緒可能會因為以下幾個原因進入阻塞狀態:

說到中斷,就會想到interrupt()方法,文件中對這個方法的功能描述是:

interrupts this thread.

但是,這個方法能不能真的輕而易舉地中斷乙個執行緒呢?我們可以用下面的**進行測試:

123

4567

891011

1213

1415

1617

1819

2021

2223

2425

2627

2829

3031

3233

/**

* 乙個簡單的只會不斷列印一句話的類

* @author psjay**/

public

class

******thread

extends

thread}}

/*** 測試類

*/public

class

test

catch

(interruptedexceptione)

}}

******thread繼承了thread,它的run()方法就是不斷地將「i am doing my job!」這句話列印到控制台。在測試類的主方法中啟動了乙個這樣的執行緒,並且主線程打算在2秒之後中斷這個執行緒。可是執行的結果並不是我們預期的那樣:控制台還是不斷地在列印「i am doing my job!」。

看來,interrupt()方法並沒有成功的中斷我們的執行緒。那麼interrupt()方法到底做了些什麼呢?

為了便於理解,其實可以這樣來模擬(注意,只是模擬,實際情況並不完全是這樣):thread類中有乙個boolean的標誌域用來表示執行緒是否需要被中斷,預設是false。interrupt()方法被呼叫之後,這個標誌域就變成了true。當然,thread類有乙個interrupted()方法返回乙個boolean值,返回的就是這個標誌域的值。也就是說,其實interrupt()方法除了把這個標誌域設定為true之後,其他什麼也沒幹了。這就解釋了上例中的執行緒為什麼不能被正確地中斷。所以,我們可以把******thread類的run()方法改寫成下面這個樣子:

123

456

@override

public

void

run()

}

再執行測試程式,就會發現,2秒後執行緒會停止列印,它確實是被中斷了。

有時候,我們不僅僅想要中斷乙個像上面這樣重複著做同一件事的執行緒。很多情況下,我們需要的是中斷乙個休眠中的執行緒。畢竟開始因為某種需要,讓乙個執行緒休眠一段很長的時間,後來你就後悔了,想中斷它的休眠。這個時候,interrupt()方法就又有用武之地了。

比如,我們有個longtimesleepthread執行緒類,他的工作就是睡之前說:「我要睡了,千萬別打攪我」,然後睡兩秒鐘,醒來之後就說:「我醒來了」。注意到,在他睡之前,他只是告訴別人:不要打攪我。但是他並不能保證別人真的不會去打攪他。所以一旦他被人打攪,就會抱怨地說一句:「有人打攪我了」。

123

4567

891011

1213

1415

1617

1819

2021

2223

2425

2627

28

/**

* 乙個在run方法中休眠2秒得執行緒類

* @author psjay**/

public

class

longtimesleepthread

extends

thread

catch

(interruptedexceptione)

system

.out

.println

("i wake up.");}

}/**

* 測試類

*/public

class

test

}

因為t並沒有被打擾,所以輸出結果是:

i want to sleep. don't bother me.

i wake up.

我們更改一下測試類,讓t在睡眠過程中被打攪:

123

4567

public

class

test

}

這個時候的輸出結果就變成了:

i want to sleep. don't bother me.

somebody bothered me.

i wake up.

乙個執行緒在休眠,不能保證不被中斷和乙個人睡覺,不能保證不被打攪是乙個道理。這就是為什麼thread的sleep()方法會可能丟擲乙個interruptedexception的原因。同樣地,thread類的join()方法,object類的wait()方法,都可能丟擲interruptedexception。

所以,如果想要中斷乙個正在sleep或者join或者wait的執行緒,呼叫執行緒的interrupt()方法即可,然後把在中斷後需要的操作寫進catch語句塊裡。

JAVA中斷執行緒的方法

thread.stop,thread.suspend,thread.resume和runtime.runfinalizersonexit這些終止執行緒執行的方法已經被廢棄,使用它們是極端不安全的!現在,如果你要安全有效地終止乙個執行緒,應該採用以下這些方法 1,執行緒正常執行完畢,正常結束。也就是讓...

Java中斷執行緒的方式

方式一 stop 方法 目前改方法已被註解 deprecated,因為它是執行緒不安全的操作,呼叫stop方法後,執行緒會立即停止,導致執行緒邏輯有一部分未執行,造成得到不可預期的結果。如下 中,預期輸出的結果是i j,但是使用stop中斷執行緒後,大概率出現j i 1.public class s...

java多執行緒學習筆記(2) 中斷執行緒

當對乙個執行緒呼叫執行緒終止方法時,執行緒的中斷狀態將被置位。這是每乙個執行緒都具有的boolean標誌。每個執行緒都應該時不時地檢查這個標誌,以判斷執行緒是否被中斷。要想弄清中斷狀態是否被置位,首先呼叫靜態的thread.currentthread方法獲得當前執行緒,然後呼叫isinterrupt...