停止執行緒


如果你想要停止一個執行緒的執行,當你查看API時,你會發現Thread的stop()方法已經被標示為deprecated,使用這個方法來停止一個執行緒是不被建議的。

請見:Why Are Thread.stop, Thread.suspend, Thread.resume and Runtime.runFinalizersOnExit Deprecated? 

如果你想要停止一個執行緒,你最好自行實作。

一個執行緒要進入死亡(Dead)狀態,就是執行完run()方法,簡單的說,如果你想要停止一個執行緒的執行,就要提供一個方式讓執行緒可以執行完run(),而這也是自行實作執行緒停止的基本概念。

例如,如果執行緒的run()方法中執行的是一個重複執行的迴圈,你可以提供一個控制旗標(Flag)來控制迴圈是否執行,藉此讓迴圈有可能終止、執行緒可以離開 run()方法以終止執行緒:
public class Some implements Runnable {
    private boolean isContinue = true;

    public void terminate() {
        isContinue = false;
    }

    public void run() {
        while(isContinue) {
            // ... some statements
        }
    }
}

如果執行緒因為執行sleep()或是wait()而進入阻斷(Blocked)或等待池(Wait)狀態,而你想要停止它,你可以使用interrupt(),而程式會丟出InterruptedException例外,因而使得執行緒 離開run()方法。例如:
  • Some.java
public class Some implements Runnable {
public void run() {
System.out.println("sleep....going to not runnable");
try {
Thread.sleep(9999);
}
catch(InterruptedException e) {
System.out.println("I am interrupted....");
}
}
}

  • Main.java
public class Main { 
public static void main(String[] args) {
Thread thread = new Thread(new Some());
thread.start();
thread.interrupt();
}
}

如果程式因為IO而進入阻斷狀態,基本上你必須等待IO完成才能離開阻斷狀態,你無法使用interrupt()來使得執行緒離開run()方法,你要提供替代的方法,基本上的概念也是引發一個例外,而這個例外要 如何引發,要看你所使用的IO而定。

例如你使用readLine()在等待網路上的一個訊息,此時執行緒進入阻斷狀態直到讀到訊息,你要讓它離開run()的方法,就是由另一個執行緒呼叫close()關閉它的串流,這時會引發一個IOException例外而使得 執行緒離開run()方法,例如:
public class Client implements Runnable {
    private Socket skt;
    // .....

    public void terminate() {
        skt.close();
    }

    public void run() {
        // .....
       
        try {
            BufferedReader buf = new BufferedReader(
               new InputStreamReader(skt.getInputStream()));

            // 讀取客戶端訊息
            // 執行readLine()會進入阻斷狀態
            // 直到讀到客戶端訊息
            while((userMessage = buf.readLine()) != null) {
               // ....
            }
        }
        catch(IOException e) {
            System.out.println("執行緒被終止.......");
        }
    }
}

上面這個程式是個簡單的架構示範,實際的設計必須視你的程式功能與IO類型而定。

除了stop()之外,suspend()、resume()方法也被標示為"deprecated",這些方法如果你要達成相同的功能,你都必須自行實作,在將來新的Java版本中如果這些功能被實現,它也可能是新的介面,而不是使用現有的方法。

有關於執行緒的終止,還可以參考 Two-phase Termination 模式