線程中斷的定義:(我的理解)就是中斷不同于終止,終止是將處于阻塞狀態(tài)的線程終止,清理資源.通常中斷的線程不在執(zhí)行狀態(tài),而是處于 sleep(),wait()等狀態(tài),線程中斷方式 Thread.interrupt().
線程停止:不管線程是否在執(zhí)行,強(qiáng)制停止,已有的過時(shí)方法 Thread.stop(),線程停止的方法目前最好的方式是用標(biāo)記位.
一 ,首先介紹Thread.interrupt()方法:
Thread類包含interrupt()方法,因此你可以終止被阻塞的任務(wù),這個(gè)方法將設(shè)置線程的中斷狀態(tài),如果一個(gè)線程已經(jīng)被阻塞,或者試圖執(zhí)行一個(gè)阻塞操作,那么設(shè)置這個(gè)線程的中斷狀態(tài)將拋出InterrupedException,當(dāng)拋出該異?;蛘咴撊蝿?wù)調(diào)用Thread.interrupt()時(shí),中斷狀態(tài)將被復(fù)位。正如你將看到的,Thread.interrupt()提供了離開run()循環(huán)而不拋出異常的第二種方式。
為了調(diào)用interrupt(),你必須持有Thread對象,新的concurrent類庫為了避免直接對Thread對象的操作,盡量通過Executor來執(zhí)行操作,如果你在Executor上調(diào)用shutdownNow(),那么將它將發(fā)送一個(gè)interrupt()調(diào)用給它啟動的所有線程,這樣會將所有阻塞的線程關(guān)閉掉.
另外一種情況是,如果只是想中斷某個(gè)任務(wù),使用Executor.submit()方法,就可以持有該任務(wù)的上下文,submit返回一個(gè)泛型Future<?>對象,通過該對象調(diào)用cancel()方法,那么實(shí)際上就調(diào)用了該線程的Thrad.interrupt()方法.
二, Executor中的shutdown()方法和shutdownNow()方法:
當(dāng)線程池調(diào)用該方法時(shí),線程池的狀態(tài)則立刻變成SHUTDOWN狀態(tài)。此時(shí),則不能再往線程池中添加任何任務(wù),否則將會拋出RejectedExecutionException異常。但是,此時(shí)線程池不會立刻退出,直到添加到線程池中的任務(wù)都已經(jīng)處理完成,才會退出.
根據(jù)JDK文檔描述,大致意思是:執(zhí)行該方法,線程池的狀態(tài)立刻變成STOP狀態(tài),并試圖停止所有正在執(zhí)行的線程,不再處理還在池隊(duì)列中等待的任務(wù),當(dāng)然,它會返回那些未執(zhí)行的任務(wù)。它試圖終止線程的方法是通過調(diào)用Thread.interrupt()方法來實(shí)現(xiàn)的,但是大家知道,這種方法的作用有限,如果線程中沒有sleep 、wait、Condition、定時(shí)鎖等應(yīng)用, interrupt()方法是無法中斷當(dāng)前的線程的,ShutdownNow()并不代表線程池就一定立即就能退出,它可能必須要等待所有正在執(zhí)行的任務(wù)都執(zhí)行完成了才能退出。
三, 線程終止安全性較高的是設(shè)置標(biāo)記位:
private? volatile boolean canceled = false;
public? void cancel(){
canceled = true;
}
@Override
public void run() {
while(!canceled){
while(true){System.out.println("# i : "+(i++)+", canceled : "+canceled);}
}
但是對于已經(jīng)開始的任務(wù),并不能馬上停止,也就是說如果里面是個(gè)執(zhí)行無限循環(huán)的任務(wù),那么還是會一直執(zhí)行下去,且這種停止的方式,并沒有清理資源,節(jié)省資源. 線程執(zhí)行完后會自動銷毀,釋放資源.
四, 線程Thread.stop方法的隱患
引用博客Java中的線程Thread方法之---stop()中的說法:調(diào)用Thread.stop()方法是不安全的,這是因?yàn)楫?dāng)調(diào)用Thread.stop()方法時(shí),會發(fā)生下面兩件事:
1. 即刻拋出ThreadDeath異常,在線程的run()方法內(nèi),任何一點(diǎn)都有可能拋出ThreadDeath Error,包括在catch或finally語句中。
2. 會釋放該線程所持有的所有的鎖,而這種釋放是不可控制的,非預(yù)期的
會產(chǎn)生的不可控現(xiàn)象一:
當(dāng)如果在給線程run方法中加同步鎖, stop方法無法停止這個(gè)線程,原因是stop方法是同步的, 所以這兩個(gè)方法持有同一個(gè)鎖
現(xiàn)象二:當(dāng)調(diào)用thread.stop()時(shí),被停止的線程會不會釋放其所持有的鎖