Java并發編程基礎(二)啟動和終止線程

通過調用線程的start()方法進行啟動,隨著run()方法的執行完畢,線程也隨之終止。

一、啟動線程


線程對象在初始化完成后,調用start()方法就可以啟動這個線程。線程start()方法的含義是:當前線程(即parent線程)同步告知Java虛擬機,只要線程規劃器空閑,應立即啟動調用start()方法的線程。

啟動一個線程前,最好為這個線程命名,方便用jstack等工具分析程序進行問題排查。

二、理解中斷


中斷好比其他線程對該線程打了個招呼,前天線程通過調用該線程的interrupt()方法對其進行中斷操作。
線程通過isInterrupted()來進行判斷是否被中斷,也可以調用靜態方法Thread.interrupted()對當前線程的中斷標識進行復位。
從Java的API中可以看到,許多聲明拋出InterruptedException的方法(例如Thread.sleep(long millis)方法)在拋出InterruptedException之前,Java虛擬機會先將該線程的中斷標識位清除,然后拋出InterruptedException,此時調用isInterrupted()方法將會返回false。
通過下面的示例可以證明:

public class Interrupted {
    
    public static void main(String[] args) throws Exception {
        // sleepThread不停的嘗試睡眠
        Thread sleepThread = new Thread(new SleepRunner(), "SleepThread");
        sleepThread.setDaemon(true);
        // busyThread不停的運行
        Thread busyThread = new Thread(new BusyRunner(), "BusyThread");
        busyThread.setDaemon(true);
        sleepThread.start();
        busyThread.start();
        // 休眠5秒, 讓sleepThread和busyThread充分運行
        TimeUnit.SECONDS.sleep(5);
        sleepThread.interrupt();
        busyThread.interrupt();
        System.out.println("SleepThread interrupted is " + sleepThread.isInterrupted());
        System.out.println("BusiThread interrupted is " + busyThread.isInterrupted());
        // 防止sleepThread和busiThread立即退出
        SleepUtils.second(2);
    }
    
    static class SleepRunner implements Runnable {
        @Override
        public void run() {
            while (true) {
                SleepUtils.second(10);
            }
        }
    }
    
    static class BusyRunner implements Runnable {
        @Override
        public void run() {
            while (true) {
                
            }
        }
    }

}

輸出如下:

SleepThread interrupted is false
BusyThread interrupted is true

三、安全地終止線程


除中斷操作外,還可以利用boolean變量來控制是否需要停止任務并終止該線程。
示例代碼,創建了一個線程CountThread,它不斷地進行變量累加,而主線程嘗試對其進行中斷操作和停止操作:

public class Shutdown {
    
    public static void main(String[] args) throws Exception {
        Runner one = new Runner();
        Thread countThread = new Thread(one, "CountThread");
        countThread.start();
        // 睡眠1秒, main線程對CountThread進行中斷, 使CountThread能夠感知中斷而結束
        TimeUnit.SECONDS.sleep(1);
        countThread.interrupt();
        
        Runner two = new Runner();
        countThread = new Thread(two, "CountThread");
        countThread.start();
        // 睡眠1秒, main線程對Runner two進行取消, 使CountThread能夠感知on為false而結束
        TimeUnit.SECONDS.sleep(1);
        two.cancel();
    }
    
    private static class Runner implements Runnable {
        private long i;
        private volatile boolean on = true;
        @Override
        public void run() {
            while (on && !Thread.currentThread().isInterrupted()) {
                i++;
            }
            System.out.println("Count i = " + i);
        }
        
        public void cancel() {
            on = false;
        }
    }

}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容