倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

Groovy で Two-Phase Termination パターン

増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編』に載っているデザインパターンを Groovy/GPars で書こうシリーズ、今回は Two-Phase Termination パターン。 このパターンでは、スレッドを終了したいときにいきなり止めるのではなく、後片付けをしましょう、ってパターンです。 ここでは、このパターンと言えるのかどうか分かりませんが、Actor のライフサイクルを利用して後片付けを行うサンプルを見ていきます。

Actor の作成方法は、Actor のサブクラスを作成する方法と Actors#actor メソッドを使用して作成する方法がありましたが、後者の方法で Actor のライフサイクルを利用する方法が分からなかったので*1、ここでは Actor のサブクラスを作成する方法だけで試しています。

サンプル・コード


このサンプルで作成するコードは

  • CountupActor クラス Actor のライフサイクルを利用して後処理を行う
  • 実行スクリプト

です。 Actor の後処理と言っても、ここでは文字列を表示するだけですが。

CountupActor クラス

Actor のライフサイクルに割り込ませることができるフックとなるメソッドは

  • afterStart
  • afterStop
  • onInterrupt
  • onTimeout
  • onException

があります。 ここでのサンプルではこれらのメソッド5つを実装していますが、後の実行スクリプトを実行して呼ばれるのは afterStart, afterStop, onInterrupt の3つです:

import groovyx.gpars.actor.DefaultActor

class CountupActor extends DefaultActor{
    
    private long counter = 0
    
    @Override
    protected void act() {
        loop{
            this.counter++
            println "count up: counter = $counter"
            Thread.sleep 500
        }
    }

    private void afterStart() {
        println "CountupActor has started"
    }

    private void afterStop(List undeliveredMessages) {
        println "CountupActor has stopped"
    }

    private void onInterrupt(InterruptedException e) {
        println "CountupActor has been interrupted"
    }

    // 下記の実行スクリプトでは使われない
    private void onTimeout() {
        println "CountupActor has timed out"
    }

    // 下記の実行スクリプトでは使われない
    private void onException(Exception e) {
        println "CountupActor threw an exception"
    }
}

実行スクリプト

実行スクリプトでは、上記の CountupActor を生成&開始した後、10000 msec 待って、Actor に対して terminate() メソッドを呼び出してます。 これを呼び出すことによって、 afterStop → onInterrupt の順で呼び出されます:

println 'main: BEGIN'

try{
   def actor = new CountupActor().start()
    
    Thread.sleep 10000
    println 'main: Termination Request'
    actor.terminate()

    println 'main: Join'
    actor.join()

}catch(InterruptedException ex){
    ex.printStackTrace()
}

println 'main: END'

ちなみに、Actor には terminate() メソッドの他に stop() メソッドってのもありますが、どう違うんでしょう・・・? 実行してみれば確かに挙動は違いますが。

増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編

増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編


プログラミングGROOVY

プログラミングGROOVY

*1:ドキュメントに載ってる方法では上手くいきませんでした。