怎么在java中關閉一個thread


怎么在java中關閉一個thread

我們經常需要在java中用到thread,我們知道thread有一個start()方法可以開啟一個線程。那么怎么關閉這個線程呢?

有人會說可以用Thread.stop()方法。但是這個方法已經被廢棄了。

根據Oracle的官方文檔,Thread.stop是不安全的。因為調用stop方法的時候,將會釋放它獲取的所有監視器鎖(通過傳遞ThreadDeath異常實現)。如果有資源該監視器鎖所保護的話,就可能會出現數據不一致的異常。並且這種異常很難被發現。 所以現在已經不推薦是用Thread.stop方法了。

那我們還有兩種方式來關閉一個Thread。

  1. Flag變量

如果我們有一個無法自動停止的Thread,我們可以創建一個條件變量,通過不斷判斷該變量的值,來決定是否結束該線程的運行。

public class KillThread implements Runnable {
    private Thread worker;
    private final AtomicBoolean running = new AtomicBoolean(false);
    private int interval;

    public KillThread(int sleepInterval) {
        interval = sleepInterval;
    }

    public void start() {
        worker = new Thread(this);
        worker.start();
    }

    public void stop() {
        running.set(false);
    }

    public void run() {
        running.set(true);
        while (running.get()) {
            try {
                Thread.sleep(interval);
            } catch (InterruptedException e){
                Thread.currentThread().interrupt();
                log.info("Thread was interrupted, Failed to complete operation");
            }
            // do something here
        }
        log.info("finished");
    }

    public static void main(String[] args) {
        KillThread killThread= new KillThread(1000);
        killThread.start();
        killThread.stop();
    }


}

上面的例子中,我們通過定義一個AtomicBoolean 的原子變量來存儲Flag標志。

我們將會在后面的文章中詳細的講解原子變量。

  1. 調用interrupt()方法

通過調用interrupt()方法,將會中斷正在等待的線程,並拋出InterruptedException異常。

根據Oracle的說明,如果你想自己處理這個異常的話,需要reasserts出去,注意,這里是reasserts而不是rethrows,因為有些情況下,無法rethrow這個異常,我們需要這樣做:

 Thread.currentThread().interrupt();

這將會reasserts InterruptedException異常。

看下我們第二種方法怎么調用:

public class KillThread implements Runnable {
    private Thread worker;
    private final AtomicBoolean running = new AtomicBoolean(false);
    private int interval;

    public KillThread(int sleepInterval) {
        interval = sleepInterval;
    }

    public void start() {
        worker = new Thread(this);
        worker.start();
    }

    public void interrupt() {
        running.set(false);
        worker.interrupt();
    }

    public void stop() {
        running.set(false);
    }

    public void run() {
        running.set(true);
        while (running.get()) {
            try {
                Thread.sleep(interval);
            } catch (InterruptedException e){
                Thread.currentThread().interrupt();
                log.info("Thread was interrupted, Failed to complete operation");
            }
            // do something here
        }
        log.info("finished");
    }

    public static void main(String[] args) {
        KillThread killThread= new KillThread(1000);
        killThread.start();
        killThread.interrupt();
    }
}

上面的例子中,當線程在Sleep中時,調用了interrupt方法,sleep會退出,並且拋出InterruptedException異常。

本文的例子請參考https://github.com/ddean2009/learn-java-concurrency/tree/master/kill-thread

更多教程請參考 flydean的博客


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM