Design Pattern: Two-phase Termination 模式
 

2009-09-21 来源:riabook.cn

 

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();
        }
    }
 }

火龙果软件/UML软件工程组织致力于提高您的软件工程实践能力,我们不断地吸取业界的宝贵经验,向您提供经过数百家企业验证的有效的工程技术实践经验,同时关注最新的理论进展,帮助您“领跑您所在行业的软件世界”。
资源网站: UML软件工程组织