java如何正確中止一個線程

Thread類中有start(), stop()方法,不過stop方法已經被廢棄掉。html

平時其實也有用過,共享一個變量,至關於標誌,不斷檢查標誌,判斷是否退出線程java

若是有阻塞,須要使用Thread的interrupt()方中斷阻塞,線程開始檢查標誌(PS:拋出異常不會退出循環)
編程

------------------------------------------------------------我是copy分割線----------------------------------------------安全

原出處:http://blog.163.com/xh_ding/blog/static/193903289201341685931689網絡

如何中止java的線程一直是一個開發多線程程序常遇到的一個問題。也有好多人問過我,因此今天在這裏總結一下但願可讓更多的人知道在java中如何安全的結束一個正在運行的線程。多線程

在Java的多線程編程中,java.lang.Thread類型包含了一些列的方法start(), stop(), stop(Throwable) and suspend(), destroy() and resume()。經過這些方法,咱們能夠對線程進行方便的操做,可是這些方法中,只有start()方法獲得了保留。
在JDK幫助文檔以及Sun公司的一篇文章《 Why are Thread.stop, Thread.suspend and Thread.resume Deprecated? 》中都講解了捨棄這些方法的緣由。
那麼,咱們究竟應該如何中止線程呢?這裏咱們介紹兩種方法:
 
1. 使用共享變量的方式

在這種方式中,之因此引入共享變量,是由於該變量能夠被多個執行相同任務的線程用來做爲是否中斷的信號,通知中斷線程的執行。
 
public class ThreadFlag extends Thread 
    public volatile boolean exit = false; 
 
    public void run() 
    { 
        while (!exit); 
    } 
    public static void main(String[] args) throws Exception 
    { 
        ThreadFlag thread = new ThreadFlag(); 
        thread.start(); 
        sleep(3000); // 主線程延遲3秒 
        thread.exit = true;  // 終止線程thread 
        thread.join(); 
        System.out.println("線程退出!"); 
    } 
在上面代碼中定義了一個退出標誌exit,當exit爲true時,while循環退出,exit的默認值爲false。在定義exit時,使用了一個Java關鍵字volatile,這個關鍵字的目的是使exit同步,也就是說在同一時刻只能由一個線程來修改exit的值。
 
在《 Why Are Thread.stop, Thread.suspend,Thread.resume and Runtime.runFinalizersOnExit Deprecated?》中,建議使用以下的方法來中止線程:
  private volatile Thread blinker; 
    public void stop() { 
        blinker = null; 
    } 
    public void run() { 
        Thread thisThread = Thread.currentThread(); 
        while (blinker == thisThread) { 
            try { 
                thisThread.sleep(interval); 
            } catch (InterruptedException e){ 
            } 
            repaint(); 
        } 
    }
 
2.  使用interrupt方法終止線程  
 
若是一個線程因爲等待某些事件的發生而被阻塞,又該怎樣中止該線程呢?這種狀況常常會發生,好比當一個線程因爲須要等候鍵盤輸入而被阻塞,或者調用Thread.join()方法,或者Thread.sleep()方法,在網絡中調用ServerSocket.accept()方法,或者調用了DatagramSocket.receive()方法時,都有可能致使線程阻塞,使線程處於處於不可運行狀態時,即便主程序中將該線程的共享變量設置爲true,但該線程此時根本沒法檢查循環標誌,固然也就沒法當即中斷。這裏咱們給出的建議是,不要使用stop()方法,而是使用Thread提供的interrupt()方法,由於該方法雖然不會中斷一個正在運行的線程,可是它可使一個被阻塞的線程拋出一箇中斷異常,從而使線程提早結束阻塞狀態,退出堵塞代碼。
 
class MyThread extends Thread {
volatile boolean stop = false;
 
public void run() {
while (!stop) {
System.out.println(getName() + " is running");
try {
sleep(1000);
} catch (InterruptedException e) {
System.out.println("week up from blcok...");
stop = true; // 在異常處理代碼中修改共享變量的狀態
}
}
System.out.println(getName() + " is exiting...");
}
}
 
class InterruptThreadDemo3 {
public static void main(String[] args) throws InterruptedException {
MyThread m1 = new MyThread();
System.out.println("Starting thread...");
m1.start();
Thread.sleep(3000);
System.out.println("Interrupt thread...: " + m1.getName());
m1.stop = true; // 設置共享變量爲true
m1.interrupt(); // 阻塞時退出阻塞狀態
Thread.sleep(3000); // 主線程休眠3秒以便觀察線程m1的中斷狀況
System.out.println("Stopping application...");
}
}
 
注意:在Thread類中有兩個方法能夠判斷線程是否經過interrupt方法被終止。一個是靜態的方法interrupted(),一個是非靜態的方法isInterrupted(),這兩個方法的區別是interrupted用來判斷當前線是否被中斷,而isInterrupted能夠用來判斷其餘線程是否被中斷。
相關文章
相關標籤/搜索