1. 程式人生 > >停止執行緒的多種方法

停止執行緒的多種方法

例一:stop強制停止執行緒

public class Thread06 extends Thread {
    private int i = 0;

    @Override
    public void run() {
        super.run();
        try{
            while(true) {
                i ++;
                System.out.println("i=" + (i + 1));
                Thread.sleep(1000);
            }
        } catch
(InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { thread06(); } private static void thread06() { try{ Thread06 thread = new Thread06(); thread.start(); Thread.sleep(9000); thread.stop(); } catch
(InterruptedException e) { e.printStackTrace(); } }

輸出結果

i=2
i=3
i=4
i=5
i=6
i=7
i=8
i=9
i=10

thread.start();方法啟動一個新的執行緒,該執行緒與main執行緒並行執行,main執行緒睡眠9秒後執行了thread.stop();方法,thread執行緒被main執行緒強制停止。

stop方法已被廢棄,因為如果強制讓執行緒停止則可能使一些清理的工作得不到完成。另外一個情況就是對鎖定的物件進行了“解鎖”,導致資料得不到同步的處理,出現數據不一致的結果。

例二:執行緒睡眠(sleep)時停止(interrupt)執行緒

public class Thread05 extends Thread {
    @Override
    public void run() {
        super.run();
        try{
            for(int i = 0; i < 1000; ++ i) {
                System.out.println("i="+(i+1));
            }
            System.out.println("run begin!");
            Thread.sleep(200000);
            System.out.println("run end!");
        } catch (InterruptedException e) {
            System.out.println("先停止,再遇到了sleep!進入catch");
            e.printStackTrace();
        }
    }
}


public static void main(String[] args) {
    thread05();
}

private static void thread05() {
    Thread05 thread = new Thread05();
    thread.start();
    thread.interrupt();
    log("end!====================");
}

輸出結果:

end!====================
i=1
i=2
i=3
......
i=999
i=1000
run begin!
先停止,再遇到了sleep!進入catch
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at com.qbian.thread.Thread05.run(Thread05.java:12)

執行緒在睡眠時(sleep)呼叫它的停止方法(interrupt)會停止執行緒並丟擲InterruptedException異常。

例三、呼叫interrupt方法停止正在執行的執行緒,break跳出迴圈繼續執行後續程式碼

public class Thread02 extends Thread{
    @Override
    public void run() {
        super.run();
        for(int i = 0; i < 500000; ++ i) {
            if(this.interrupted()) {
                System.out.println("已經是停止狀態了!我要退出了!");
                break;
            }
            System.out.println("i=" + ( i + 1));
        }
        System.out.println("我被輸出,執行緒並沒有完全停止!");
    }
}


public static void main(String[] args) {
    thread02();
}

private static void thread02() {
    try{
        Thread02 thread = new Thread02();
        thread.start();
        Thread.sleep(2000);
        thread.interrupt();
    } catch(InterruptedException e) {
        log("main catch");
        e.printStackTrace();
    }
    log("end!");
}

輸出結果:

......
i=245329
i=245330
i=245331
i=245332
i=245333
i=245334
end!
已經是停止狀態了!我要退出了!
我被輸出,執行緒並沒有完全停止!

break只是跳出了for迴圈,並不會真正的停止執行緒,run方法內的後續程式碼會繼續執行。

例四、呼叫interrupt方法停止正在執行的執行緒,並丟擲異常阻止執行緒後續的程式碼執行

public class Thread03 extends Thread {
    @Override
    public void run() {
        super.run();
        try{
            for(int i = 0; i < 500000; ++ i) {
                if(this.interrupted()) {
                    System.out.println("已經是停止狀態了!我要退出了!");
                    throw new InterruptedException();
                }
                System.out.println("i=" + ( i + 1));
            }
            System.out.println("因為丟擲了異常,所以我不會被輸出!");
        } catch(InterruptedException e) {
            System.out.println("進thread03類的run方法中的catch了!");
            e.printStackTrace();
        }
    }
}


public static void main(String[] args) {
    thread03();
}

private static void thread03() {
    try{
        Thread03 thread = new Thread03();
        thread.start();
        Thread.sleep(2000);
        thread.interrupt();
    } catch(InterruptedException e) {
        log("main catch");
        e.printStackTrace();
    }
    log("end!");
}

輸出結果:

......
i=278267
i=278268
i=278269
i=278270
i=278271
已經是停止狀態了!我要退出了!
end!
進thread03類的run方法中的catch了!
java.lang.InterruptedException
    at com.qbian.thread.Thread03.run(Thread03.java:11)

主執行緒呼叫interrupt方法停止一個正在執行的執行緒,在被停止的執行緒內部判斷自身狀態是否已經停止this.interrupted(),停止的話就丟擲異常,可以阻止後續程式碼的執行,直接進入catch塊內。

例五、使用interrupt和return停止執行緒並阻止後續程式碼執行

public class Thread07 extends Thread{
    @Override
    public void run() {
        super.run();
        while(true) {
            if(this.isInterrupted()) {
                System.out.println("停止了!後面的時間將不會被輸出!");
                return;
            }
            System.out.println("timer=" + System.currentTimeMillis());
        }
    }
}


public static void main(String[] args) {
    thread07();
}

private static void thread07() {
    try {
        Thread07 thread = new Thread07();
        thread.start();
        Thread.sleep(2000);
        thread.interrupt();
    } catch (InterruptedException e) {
        log("main catch");
        e.printStackTrace();
    }

}

輸出結果:

......
timer=1496420116082
timer=1496420116082
timer=1496420116082
停止了!後面的時間將不會被輸出!

推薦使用丟擲異常的方式停止執行緒執行,因為在catch塊中還可以將異常向上拋,使執行緒停止的事件得到傳播。