天天看點

對Thread.interrupt()方法很詳細的介紹

在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!