在jdk1.0中,可以用stop方法來終止,但是現在這種方法已經被禁用了,改用interrupt方法。
thread.interrupt()方法不會中斷一個正在運作的線程。它的作用是,線上程受到阻塞時抛出一個中斷信号,這樣線程就得以退出阻塞的狀态。更确切的說,如果線程被object.wait, thread.join和thread.sleep三種方法之一阻塞,那麼,它将接收到一個中斷異常(interruptedexception),進而提早地終結被阻塞狀态。
interrupt方法并不是強制終止線程,它隻能設定線程的interrupted狀态,而線上程中一般使用一下方式:
while (!thread.currentthread().isinterrupted() && more work to do)
{...}
而被block的線程(sleep() or join())在被調用interrupt時會産生interruptexception,此時是否終止線程由本線程自己決定。程式的一般形式是:
public void run()
{
try
. . .
while (!thread.currentthread().isinterrupted() && more work to do)
do more work
}
catch(interruptedexception e)
// thread was interrupted during sleep or wait
finally
cleanup, if required
// exiting the run method terminates the thread
thread.sleep方法也會産生interruptedexception,是以,如果每次在做完一些工作後調用了sleep方法,那麼就不用檢查isinterrupted,而是直接捕捉interruptedexception。
---------------------------------------------------------------------------------------
假如我們有一個任務如下,交給一個java線程來執行,如何才能保證調用interrupt()來中斷它呢?
class atask implements runnable{
private double d = 0.0;
public void run() {
//死循環執行列印"i am running!" 和做消耗時間的浮點計算
while (true) {
system.out.println("i am running!");
for (int i = 0; i < 900000; i++) {
d = d + (math.pi + math.e) / d;
}
//給線程排程器可以切換到其它程序的信号
thread.yield();
}
}
}
public class interrupttasktest {
public static void main(string[] args) throws exception{
//将任務交給一個線程執行
thread t = new thread(new atask());
t.start();
//運作一斷時間中斷線程
thread.sleep(100);
system.out.println("****************************");
system.out.println("interrupted thread!");
t.interrupt();
}
運作這個程式,我們發現調用interrupt()後,程式仍在運作,如果不強制結束,程式将一直運作下去,如下所示:
......
i am running!
****************************
interrupted thread!
....
雖然中斷發生了,但線程仍然在進行,離開線程有兩種常用的方法:
抛出interruptedexception和用thread.interrupted()檢查是否發生中斷,下面分别看一下這兩種方法:
1.在阻塞操作時如thread.sleep()時被中斷會抛出interruptedexception(注意,進行不能中斷的io操作而阻塞和要獲得對象的鎖調用對象的synchronized方法而阻塞時不會抛出interruptedexception)
java代碼
try {
while (true) {
system.out.println("i am running!");
for (int i = 0; i < 900000; i++) {
d = d + (math.pi + math.e) / d;
}
//休眠一斷時間,中斷時會抛出interruptedexception
thread.sleep(50);
} catch (interruptedexception e) {
system.out.println("atask.run() interrupted!");
程式運作結果如下:
atask.run() interrupted!
可以看到中斷任務時讓任務抛出interruptedexception來離開任務.
2.thread.interrupted()檢查是否發生中斷.thread.interrupted()能告訴你線程是否發生中斷,并将清除中斷狀态标記,是以程式不會兩次通知你線程發生了中斷.
//檢查程式是否發生中斷
while (!thread.interrupted()) {
d = d + (math.pi + math.e) / d;
system.out.println("atask.run() interrupted!");
程式運作結果如下:
我們可結合使用兩種方法來達到可以通過interrupt()中斷線程.請看下面例子:
//point1 before sleep
thread.sleep(20);
//point2 after sleep
system.out.println("calculating");
system.out.println("exiting by exception");
在point1之前處point2之後發生中斷會産生兩種不同的結果,可以通過修改interrupttasktest main()裡的thread.sleep()的時間來達到在point1之前産生中斷或在point2之後産生中斷.
如果在point1之前發生中斷,程式會在調用thread.sleep()時抛出interruptedexception進而結束線程.這和在thread.sleep()時被中斷是一樣的效果.程式運作結果可能如下:
calculating
exiting by exception
如果在point2之後發生中斷,線程會繼續執行到下一次while判斷中斷狀态時.程式運作結果可能如下:
atask.run() interrupted!