天天看點

對線程的中斷

這裡我們先來講一下已經被棄用的 stop() 以及 suspend() 這兩個方法

stop()

反對使用stop(),是因為它不安全。它會解除由線程擷取的所有鎖定,當在一個線程對象上調用stop()方法時,這個線程對象所運作的線程就會立即停止,假如一個線程正在執行:synchronized void { x = 3; y = 4;} 由于方法是同步的,多個線程通路時總能保證x,y被同時指派,而如果一個線程正在執行到x = 3;時,被調用了 stop()方法,即使在同步塊中,它也幹脆地stop了,這樣就産生了不完整的殘廢資料。而多線程程式設計中最最基礎的條件要保證資料的完整性,是以請忘記線程的stop方法,以後我們再也不要說“停止線程”了。而且如果對象處于一種不連貫狀态,那麼其他線程能在那種狀态下檢查和修改它們。結果很難檢查出真正的問題所在。

suspend()

suspend()方法容易發生死鎖。調用suspend()的時候,目标線程會停下來,但卻仍然持有在這之前獲得的鎖定。此時,其他任何線程都不能通路鎖定的資源,除非被"挂起"的線程恢複運作。對任何線程來說,如果它們想恢複目标線程,同時又試圖使用任何一個鎖定的資源,就會造成死鎖。是以不應該使用suspend(),而應在自己的Thread類中置入一個标志,指出線程應該活動還是挂起。若标志指出線程應該挂起,便用 wait()命其進入等待狀态。若标志指出線程應當恢複,則用一個notify()重新啟動線程。

執行線程如何獲得自己的中斷标志

1、Thread.currentThread.isInterrupted()  擷取目前線程的中斷标志

2、Thread.interrupted () 擷取并重置中斷标記值,并會将标記值重新設定為 false;

如何設定另外一個線程的中斷标志

執行線程調用一個線程的 Interrupt() 将目标線程的中斷标志設定為 true.

如何設定一個程序讓其響應中斷停止下來

第一種方式:

通過上面的知識點我們可以知道通過設定另外一個線程的中斷标志更改為true 就能夠将其進行終止下來,案例如下

private BlockingQueue<Runnable> chanel;
    class WorkerTherad extends Thread{
        @Override
        public void run(){
            Runnable task = null;
            try {
                for (;;){
                    try {
                        task = chanel.take();
                    } catch (Throwable e) {
                        e.printStackTrace();
                    }
                }
            }catch (InterruptedException e){

            }
        }
    }
           

乍一看這個貌似乎好像也是可以響應中斷 然後停止線程的運作的,但是還有一點情況是,當線程正在執行器内部可以抛出異常的步驟當中,我們外部線程所發過去的中斷指令會被其捕獲,然後并不會中斷我們的線程,線程依然執行着。從這裡可以看出我們的中斷指令被“吞沒”;我們可以看第二種方式對其進行一個緩和解決。

第二種方式:使用 interrupt() 方法 + 外加一個中斷變量

public volatile boolean inUse = true;
    private BlockingQueue<Runnable> chanel;
    public WorkerTherad workerTherad = new WorkerTherad();
    public void shutdown(){
        inUse =false;
        final Thread t = workerTherad;
        if (null!=t){
            t.interrupt();
        }
    }
    class WorkerTherad extends Thread{
        @Override
        public void run(){
            Runnable task = null;
            try {
                for (;;){
                    if (!inUse&&chanel.isEmpty()){
                        break;
                    }
                    try {
                        task = chanel.take();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }catch (InterruptedException e){

            }
        }
    }
           

通過 外加一個中斷标志變量,盡管我們的中斷指令被吞噬,但是我們的目标線程還是依然有退路的,他能通過對線程停止标志的判斷而進行停止。

繼續閱讀