java thread stop中止線程 不拋出異常 沒有異常信息

前言

Thread的實例方法stop()用來中止線程,它是真正的中止線程,與之相對應的interrupt()是一種提示性中止,因爲沒有留出機會讓程序員處理資源,stop()會帶來狀態一致性問題,所以已不推薦使用,不過這裏是爲了探究爲什麼不推薦使用,所以研究。

中止線程

public class MyThread extends Thread {


    @Override
    public void run() {
        System.out.println("begin");
        try {
            this.stop();
        } catch (ThreadDeath e) {
            System.out.println("進入catch塊了");
            e.printStackTrace();
        }
        System.out.println("end");
    }
}

public class StopRun {
    public static void main(String[] args) throws InterruptedException {

        MyThread myThread = new MyThread();
        myThread.start();


    }
}

輸出結果

java.lang.ThreadDeath
	at java.lang.Thread.stop(Thread.java:850)
	at extthread.MyThread.run(MyThread.java:13)
begin
進入catch塊了
end

根據java api所述,

無論該線程在做些什麼,它所代表的線程都被迫異常停止,並拋出一個新創建的 ThreadDeath 對象,作爲異常。

通過輸出可以看到的確拋出了ThreadDeath,以上示例是參考《Java多線程編程核心技術》一書所寫,在實踐中我稍微改了一下卻發現,沒有任何異常信息。

public class MyThread extends Thread {


    @Override
    public void run() {
        System.out.println("begin");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("end");
    }
}
public class StopRun {
    public static void main(String[] args) throws InterruptedException {

        MyThread myThread = new MyThread();
        myThread.start();
		//讓myThread得到機會運行
        Thread.sleep(200);
        myThread.stop();

    }
}

此種寫法,控制檯什麼也沒輸出!當時我就納悶了?不應該呀,按照api,stop()方法肯定會拋出ThreadDeath。後來一想,拋出的異常應該在目標線程拋出,而非執行線程拋出,在本例中myThread是目標線程,主線程是執行線程。果斷將MyThread的run()方法,try catch,經此一改,果然出現異常信息了

 @Override
    public void run() {
        try {
            System.out.println("begin");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }catch (ThreadDeath e){
            e.printStackTrace();
        }
        System.out.println("end");
    }

輸出結果

begin
java.lang.ThreadDeath
	at java.lang.Thread.stop(Thread.java:850)
	at test.StopRun.main(StopRun.java:14)
end

ThreadDeath

順便提一下ThreadDeath,按照api規定,stop()時會拋出ThreadDeath,ThreadDeath是繼承自Error,而非Exception子類,通常情況下,是不需要catch的,上邊的例子只是爲了演示,所以catch。所以在catch時,應該catch(Error)或者catch(ThreadDeath),而不應該catch(Exception),catch(Exception)也不會打印異常信息。
在這裏插入圖片描述

狀態一致性問題

stop()屬於暴力強制中止線程,會帶來狀態一致性問題。

public class SynchronizedObject {

    private String userName = "a";
    private String password = "aa";

    public synchronized  void printString(String userName, String password){

        try {
            this.userName = userName;
            Thread.sleep(100000);
            this.password = password;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}
public class SynchronizedThread extends Thread {

    private SynchronizedObject object;

    public SynchronizedThread(SynchronizedObject object) {
        this.object = object;
    }

    @Override
    public void run() {
        object.printString("b","bbb");
    }
}
 public static void main(String[] args) throws InterruptedException {
        SynchronizedObject object = new SynchronizedObject();
        SynchronizedThread t = new SynchronizedThread(object);
        t.start();
        Thread.sleep(500);
        t.stop();
        System.out.println(object.getUserName()+"-"+object.getPassword());

    }

輸出結果,可以看到因爲stop()的強制中止,沒有給程序員預留善後空間,導致狀態不一致;理論上,使用stop()的地方都應該使用interrupt()代替;

b-aa

參考

java多線程編程核心技術 高洪巖著

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章