1. 程式人生 > >[25]stop方法被拋棄的原因和代替方法

[25]stop方法被拋棄的原因和代替方法

在JAVA API中寫著:

stop()方法無論執行緒在什麼狀態下所代表的執行緒都將被強制停止

class ThreadStop implements Runnable{
    private int num;
    @override
    public void run(){
        while(count<10){
            try{
                Thread.sleep(300);
            }catch(InterruputExpcetion e){
                e.printStackTrace();
            }
        }
    System.out.println(Thread.currentThread().getName()+" : stop");
    }
}

class Demo{
    public static void main(String[] args){
        ThreadStop stop=new ThreadStop();
        Thread t1=new Thread(stop);

        t1.start();

        try{
            Thread.sleep(2000);
        }catch(InterruputExpcetion e){
            e.printStackTrace();
        }
        t1.stop;

        System.out.println(Thread.currentThread().getName+" : stop");
    }
}

執行結果:

Thread-0 : 0
Thread-0 : 1
Thread-0 : 2
Thread-0 : 3
Thread-0 : 4
Thread-0 : 5
Thread-0 : 6
main : stop

執行結果中,缺少了Thread-0 : stop。因為執行緒已經被強制停止了。後續的內容也不會再執行,這是stop()的作用也是缺點。如果在後面寫的不是輸出語句,而是釋放資源的內容那麼影響就比較的大了

所以,API裡面也介紹了這麼一段話:

stop 的許多使用都應由只修改某些變數以指示目標執行緒應該停止執行的程式碼來取代。目標執行緒應定期檢查該變數,並且如果該變數指示它要停止執行,則從其執行方法依次返回。如果目標執行緒等待很長時間(例如基於一個條件變數),則應使用 interrupt

 方法來中斷該等待。

簡而言之:

停止執行緒的程式碼不用stop()而是定義一個變數來取代,並且需要定期檢查(while條件),如果目標執行緒需要等待很長時間(如果sleep(300)變成了wait(),那麼就是長時間的等待了),則應使用interruput來中斷。

interrupt():API中介紹是在用到sleep(),wait(),join()無參或有參方法時受阻,那麼清除其中斷狀態,並返回一個異常。

所以改進如下

class ThreadStop implements Runnable{
    private int num;
    private boolean flag;//標記,也就是用來替代stop()的變數
    /*因為需要用到wait()所以加上synchronized也可以使用同步程式碼塊*/
    @override
    public synchronized void run(){
        while(!flag){
           if(num==5){
             try{
                this.wait();//等待時間過長
             }catch(InterruputExpcetion e){
/*因為目的是停止執行緒,wait()被中斷了,所以執行異常內容,因為要停止,那麼要先使判斷條件為false*/
                changeFlag();
                e.printStackTrace();
                }    
            }
        }
    System.out.println(Thread.currentThread().getName()+" : stop");
    }
    /*如果程式需要停止,改變flag的值,得到stop()的作用*/
    public void changeFlag(){
        this.flag=!flag;
    }
}

class Demo{
    public static void main(String[] args){
        ThreadStop stop=new ThreadStop();
        Thread t1=new Thread(stop);

        t1.start();

        try{
            Thread.sleep(2000);
        }catch(InterruputExpcetion e){
            e.printStackTrace();
        }
        t1.interrupt();//因為t1執行緒wait()受阻,等待時間過長,所以用interrupt()來中斷

        System.out.println(Thread.currentThread().getName+" : stop");
    }
}

輸出結果:

Thread-0 : 0
Thread-0 : 1
Thread-0 : 2
Thread-0 : 3
Thread-0 : 4
main : stop
java.lang.InterruptedException
Thread-0 : stop
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Unknown Source)
    at com.stop.ThreadStop.run(ThreadStop.java:15)
    at java.lang.Thread.run(Unknown Source)

其中 java.lang.InterruptedException為interrupt()返回的異常。

而下面一大串的異常,是因為wait()被中斷,所以丟擲的異常。

並且也可以看到之前缺少的Thread-0 : stop

 

所以總結一下:

stop()被拋棄的原因
1.雖然停止了執行緒,但是執行緒並未執行完,會導致沒有釋放資源

解決方案

1.將interrupt()用來代替stop()
2.interrupt()是清除中斷狀態的,並不是終止執行緒
所以如果只是將stop替換成interrupt的話,那程式會繼續執行,並沒有終止
3.所以用一個標記來結束迴圈條件,並寫一個修改標記的放在catch中