天天看點

并發(十三):線程都可以中斷嗎?

在長任務的運作過程中,有時我們需要提前中斷任務的執行,以保持對使用者操作的響應性,而在新版JAVA中,已沒有能終止線程執行的方法(Thread.stop()已廢除),在Thread提供的内置方法中,能影響Thread執行節奏的方法也就隻有interrupt()了,那麼所有的線程都能對中斷進行響應嗎?

看如下的例子:

static class PrimeThread extends Thread {

    public void run() {
        try {
            //  無限循環
            while(true) {
                //  處理具體的業務
                Thread.yield();
            }
        } finally {
            //  隻要有異常,則進入此執行步驟
            System.out.println("線程已終結");
            System.exit();
        }

    }

}
           

啟動線程與中斷的代碼如下:

PrimeThread pt = new PrimeThread();
pt.start();
System.out.println("準備中斷!");
//  中斷線程
pt.interrupt();
           

在上面的例子中,雖然我們調用了interrupt()方法,但線程始終都無法響應中斷請求,原因在于我們的業務代碼都是無法響應中斷請求的。

換種說法,主要是我們代碼中的Thread.yield()沒有抛出中斷異常,換為Thread.sleep()則可以正常進行中斷請求,這也是Thread.yield()與Thread.sleep()的另一個差別。

另外需要注意的是,即使我們的代碼能夠響應中斷,但在一次循環沒有完成之前,或者說沒有執行到能夠響應中斷的指令位置,依舊無法響應中斷。

結論

Thread.interrupt隻是為線程增加了中斷狀态,還需要我們進行手動處理,更重要的是,我們調用的代碼還必須支援中斷狀态的響應(能捕獲中斷異常,請參見本例中Thread.yield()與Thread.sleep()的差異),另外,從上面的例子可以看出,如果能讓線程抛出異常,也是中斷線程的一種方法,如提前調用InputStream的close()方法。