Java多线程设计模式(4)

《Java多线程设计模式》读书笔记4 -- Two-phase Termination

Two-phase Termination模式就是让线程正常结束,也就是结束之前进行一些善后处理,释放掉该释放的资源,完成自己当前的任务。在Java语言中,有一个方法stop,这个方法会使当前线程结束,但是不应该使用这个方法,因为他将会导致灾难性的后果。应该使用设置标志的方法来替代stop方法。

转一篇关于该模式的博文http://www.blogjava.net/jesson2005/articles/111202.html

Two-phase Termination直譯的話是「兩相終止」,不過就這個模式而言,該譯作「兩階段終止」比較適當,想像您有一個執行緒正在週期性的運作,在「運作階段」您送出了停止執行緒的請求,這時候執行緒不該慌張的馬上終止目前的工作,而是先完成這一次週期的工作,然後進入「善後階段」完成一些善後的工作,例如關閉檔案或網路串流,所謂的兩階段終止,即中止「運作階段」,並完成「善後階段」,完整的完成執行緒的工作。

以Java的Thread終止而言,不建議您直接使用stop()方法來終止執行緒,stop()方法會丟出ThreadDeath例外強迫執行緒終止,即使執行緒正在運作階段或執行至synchronized區,如果您要終止執行緒,建議自行實作,例如:

  public class SomeThread extends Thread {
    private boolean isTerminated = false;

    public void terminate() {
        isTerminated = true;
    }

    public void run() {
        while(!isTerminated) {
            // ... some statements
        }
    }
}

考慮到有時執行緒可能會執行至sleep()或wait()而進入Not Runnable狀態,使用上面的方法可能會延遲終止的請求,因而可以在要求終止時再呼叫interrupt()方法,這會丟出 InterruptedException,而使得執行緒從Not Runnable狀態中離開,因此可以改變一下程式:

public class SomeThread extends Thread {
    private boolean isTerminated = false;

    public void terminate() {
        isTerminated = true;
        interrupt();
    }

    public void run() {
        try {
            while(!isTerminated) {
                // ... some statements
            }
        }
        catch(InterruptedException e) {
        }
    }
}

在發出中止請求之後,如果執行緒是在Not Runnable狀態,會丟出InterruptedException,如果這個例外沒有先被捕捉,就會被run()中的catch InterruptedException捕捉,也就是說會直接離開while迴圈,因而如果您在發出終止請求後,要求先執行完這一個週期的工作,您要先捕捉這個例外,若不用完成這一個週期的工作,則不用捕捉這個例外,要如何作取決於您的程式。

如果執行緒要完成這一個週期的工作,在下一個週期開始之前檢查旗標,這時它的結果是false,所以離開while迴圈,這時候您可以進行一些善後工作,這個可以寫在finally區塊中,例如:

public class SomeThread extends Thread {
    private boolean isContinue = false;

    public void terminate() {
        isTerminated = true;
        interrupt();
    }

    private void doWorkBeforeShutdown() {
        // .... do some work before shutdown
    }

    public void run() {
        try {
            while(!_isTerminated) {
                // ... some statements
            }
        }
        catch(InterruptedException e) {
        }
        finally {
            doWorkBeforeShutdown();
        }
    }
}

上面這個程式大致上就是Two-phase Termination模式的架構,另外如果您的執行緒還服務著其它的物件,則在送出終止請求到完全終止之前,應該停止服務其它物件,您可以讓其它物件要求服務之前,先查詢執行緒是否已被要求終止,這可以藉由提供一個方法來達到:

public class SomeThread extends Thread {
    private boolean isTerminated = false;

    public void terminate() {
        isTerminated = true;
        interrupt();
    }

    public boolean isTerminated() {
        return _isTerminated;
    }

    private void doWorkBeforeShutdown() {
        // .... do some work before shutdown
    }

    public void run() {
        try {
            while(!_isTerminated) {
                // ... some statements
            }
        }
        catch(InterruptedException e) {
        }
        finally {
            doWorkBeforeShutdown();
        }
    }
}

posted @ 2010-06-10 15:06  gshine  阅读(316)  评论(0编辑  收藏  举报