83.4. デシジョンエンジンにおけるルール実行モードおよびスレッドの安全性

デシジョンエンジンは、デシジョンエンジンがルールを実行する方法とタイミングを決定する以下のルール実行モードをサポートします。

  • パッシブモード: (デフォルト) デシジョンエンジンは、ユーザーまたはアプリケーションが fireAllRules() を明示的に呼び出す時にルールを評価します。デシジョンエンジンのパッシブモードは、ルールの評価および実行を直接管理する必要があるアプリケーションにとって、またはデシジョンエンジンで擬似クロック実装を使用する複合イベント処理 (CEP) のアプリケーションにとって最適です。

    パッシブモードのデシジョンエンジンを使用した CEP アプリケーションのコード例

    KieSessionConfiguration config = KieServices.Factory.get().newKieSessionConfiguration();
    config.setOption( ClockTypeOption.get("pseudo") );
    KieSession session = kbase.newKieSession( conf, null );
    SessionPseudoClock clock = session.getSessionClock();
    
    session.insert( tick1 );
    session.fireAllRules();
    
    clock.advanceTime(1, TimeUnit.SECONDS);
    session.insert( tick2 );
    session.fireAllRules();
    
    clock.advanceTime(1, TimeUnit.SECONDS);
    session.insert( tick3 );
    session.fireAllRules();
    
    session.dispose();

  • アクティブモード: ユーザーまたはアプリケーションが fireUntilHalt() を呼び出す場合、デシジョンエンジンはアクティブモードで開始し、ユーザーまたはアプリケーションが明示的に halt() を呼び出すまで、継続的にルールを評価します。デシジョンエンジンのアクティブモードは、デシジョンエンジンにルールの評価と実行の管理を委譲するアプリケーションにとって、またはデシジョンエンジンでリアルタイムクロックの実装を使用する複合イベント処理 (CEP) アプリケーションにとって最適です。アクティブモードは、アクティブなクエリーを使用する CEP アプリケーションにも最適です。

    アクティブモードのデシジョンエンジンを使用した CEP アプリケーションのコード例

    KieSessionConfiguration config = KieServices.Factory.get().newKieSessionConfiguration();
    config.setOption( ClockTypeOption.get("realtime") );
    KieSession session = kbase.newKieSession( conf, null );
    
    new Thread( new Runnable() {
      @Override
      public void run() {
          session.fireUntilHalt();
      }
    } ).start();
    
    session.insert( tick1 );
    
    ... Thread.sleep( 1000L ); ...
    
    session.insert( tick2 );
    
    ... Thread.sleep( 1000L ); ...
    
    session.insert( tick3 );
    
    session.halt();
    session.dispose();

    この例では、デシジョンエンジンがルールの評価を継続している間に、現在のスレッドが永久にブロックされないように、専用の実行スレッドから fireUntilHalt() を呼び出します。また、専用のスレッドにより、アプリケーションコードの後の段階で halt() を呼び出すこともできます。

fireAllRules() および fireUntilHalt() の両方を呼び出すのは避けるべきですが (特に異なるスレッドからの場合)、デシジョンエンジンは、スレッドの安全性の論理および内部状態マシンを使用してこのような状況を安全に処理できます。fireAllRules() の呼び出し中に fireUntilHalt() を呼び出す場合、デシジョンエンジンは、fireAllRules() の操作が完了し、fireUntilHalt() の呼び出しに対応してアクティブモードで開始するまで、パッシブモードでの実行を続けます。しかし、デシジョンエンジンが、アクティブモードで実行中に、fireUntilHalt() の呼び出しに続いて fireAllRules() を呼び出すと、fireAllRules() の呼び出しは無視され、デシジョンエンジンは halt() が呼び出されるまで、アクティブモードでの実行を続けます。

アクティブモードでのスレッドの安全性を高めるため、デシジョンエンジンは、submit() メソッドをサポートします。このメソッドは、スレッドセーフでアトミックなアクションの KIE セッションで、操作をグループ化および実行するために使用できます。

アクティブモードでアトミック操作を実行する submit() メソッドを使用したアプリケーションのコード例

KieSession session = ...;

new Thread( new Runnable() {
  @Override
  public void run() {
      session.fireUntilHalt();
  }
} ).start();

final FactHandle fh = session.insert( fact_a );

... Thread.sleep( 1000L ); ...

session.submit( new KieSession.AtomicAction() {
  @Override
  public void execute( KieSession kieSession ) {
    fact_a.setField("value");
    kieSession.update( fh, fact_a );
    kieSession.insert( fact_1 );
    kieSession.insert( fact_2 );
    kieSession.insert( fact_3 );
  }
} );

... Thread.sleep( 1000L ); ...

session.insert( fact_z );

session.halt();
session.dispose();

スレッドの安全性とアトミック操作は、クライアントサイドパースペクティブからも役に立ちます。たとえば、複数のファクトを指定の時間に挿入する必要があるものの、デシジョンエンジンが挿入をアトミック操作とみなし、すべての挿入が完了してからルールの再評価を始める必要がある場合などです。