java 兩階段終止線程的正確做法

一、怎麼優雅地關閉一個線程?

在一個線程T1中如何優雅地關閉線程T2(也就是說要給T2一個機會釋放持有的資源)?

1.錯誤做法

使用stop()方法停止線程:

stop()方法會真正殺死線程,如果此時該線程持有鎖,那麼其他線程將永遠無法獲取鎖。

使用System.exit()方法停止線程:

會讓整個進程都退出

2.正確做法

思路:

代碼實現:

public class Test {
    public static void main(String[] args) throws InterruptedException {
        TwoPhaseTermination twoPhaseTermination = new TwoPhaseTermination();
        twoPhaseTermination.start();

        Thread.sleep(3000);
        twoPhaseTermination.stop();

    }
}

class TwoPhaseTermination{
    // 監控線程
    private Thread monitorThread;

    public void start(){
        monitorThread = new Thread(()->{
            Thread current = Thread.currentThread();
            while(true){
                if(current.isInterrupted()){

                    System.out.println("線程要關閉瞭...");
                    break;
                }
                try {
                    Thread.sleep(1000); // 階段1
                    System.out.println("監控線程正在工作...."); // 階段2
                     // 如果在階段2被打斷,線程的isInterrupted標志位為true,會捕抓到信號並關閉線程
                     // 如果在階段1被打斷,會進入catch語句塊,並且isInterrupted標志位清空,無法關閉線程
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    // 需要重新設置isInterrupted標志位為true
                    monitorThread.interrupt();
                }
            }

        });
        // 啟動線程
        monitorThread.start();
    }

    public void stop(){
        // 設置isInterrupted標志位true
        monitorThread.interrupt();
    }
}

運行結果:

兩階段關閉線程:

二、要點

為什麼需要在catch代碼塊中重新執行monitorThread.interrupt()?因為Thread.sleep()執行過程中被打斷,isInterrupted標志位會清空,下一次進入while循環就會忽略這次打斷,繼續運行線程。

演示一下把monitorThread.interrupt()註釋掉的結果:

可以看到,會忽略這次的isInterrupted信號,繼續運行線程。

到此這篇關於java 兩階段終止線程的正確做法的文章就介紹到這瞭,更多相關java 兩階段終止線程內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: