1. 程式人生 > >停止中斷執行緒的方法

停止中斷執行緒的方法

Thread.run執行完畢,執行緒就結束了;

Thread.stop:雖然確實可以停止一個正在執行的執行緒,但是這種方法是不安全的,也不被提倡;

Thread.interrupt:並不會中斷一個正在執行的執行緒

中斷執行緒最好的,最受推薦的方式是使用共享變數發出訊號,告訴執行緒必須停止當前任務,而執行緒需要週期性地檢查這一變數,然後有秩序地終止任務(沒有用到interrupt方法,共享變數是volatile型別或將對它的一切訪問封裝到同步塊/方法中);

但是,當執行緒因等待某些事件發生而被阻塞,便不能核查共享變數,也就不能停止,所以需要某種機制使得執行緒更早地退出被阻塞的狀態。
Thread.interrupt實際完成的是,線上程受到阻塞時丟擲一箇中斷訊號,這樣執行緒就可以退出阻塞狀態,更確切地說,如果執行緒被Object.wait,Thread.join和Thread.sleep三種方法之一阻塞,就會接到一個InterruptedException,從而提早結束阻塞狀態。

因此,如果執行緒被上述幾種方式阻塞,正確的停止方式是:先設定共享變數,再呼叫interrupt方法,如果執行緒沒有被阻塞,這時interrupt將不起作用;否則,執行緒將得到異常,並逃離阻塞狀態。
程式碼示例:
public class Test {
    
    public static void main(String[] args) throws InterruptedException {
        MyThread t = new MyThread();
        System.out.println("Start thread...");
        t.start();
        Thread.sleep(3000);
        System.out.println("Ask thread to stop...");
        t.stop = true;
        t.interrupt();
        Thread.sleep(3000);
        System.out.println("stop...");
    }
    
    static class MyThread extends Thread {
        
        static volatile boolean stop = false;
        public void run() {
            while(!stop) {
                try {
                    Thread.sleep(1000);
                    System.out.println("MyThread running...");
                } catch (InterruptedException e) {
                    System.out.println("MyThread interrupted...");
                }
            }
            System.out.println("MyThread exist under request...");
        }
    }
}


執行結果:
Start thread...
MyThread running...
MyThread running...
Ask thread to stop...
MyThread interrupted...
MyThread exist under request...
stop...

中斷I/O操作:
I/O操作可以阻塞執行緒一段相當長的時間,特別是牽扯到網路應用時。例如,伺服器可能要等待一個請求(request),又或者,一個網路應用程式可能要等待 遠端主機的響應。
如果正在使用通道(channels,在Java4中引入的I/O API),那麼被阻塞的執行緒將收到一個ClosedByInterruptException異常,如果情況是這樣,程式碼邏輯和上面的程式碼是相同的,只不過異常不同;

但是,如果使用的是Java 1.0之前的傳統I/O,Thread.interrupt將不起作用,因為執行緒將不會退出被阻塞的狀態。此時,Java平臺的解決方案為:呼叫阻塞該執行緒的套接字Socket的close方法,在這種情形下,如果執行緒被I/O操作阻塞,該執行緒將接收一個SocketException,這與interrupt方法引起的InterruptedException異常非常相似。唯一要說明的是,必須存在socket的引用,只有這樣close方法才能被呼叫,這意味著socket物件必須被共享。