80.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();Active 模式 :如果用户或应用程序调用
fireUntilHalt (),决策引擎以 active 模式启动,并持续评估规则,直到用户或应用程序显式调用halt ()。决策引擎中的活跃模式最适合将规则评估和执行控制委派给决策引擎,或用于在决策引擎中使用实时时钟实现的复杂事件处理(CEP)应用程序。Active 模式也是使用活跃查询的 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 () 之前继续运行。
对于以活跃模式添加线程安全性,决策引擎支持 提交() 方法,您可以在线程安全、原子操作中对 KIE 会话进行分组和执行操作:
带有 commit () 方法的应用程序代码示例,用于在主动模式下执行原子操作
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();
从客户端角度而言,线程安全性和原子操作也很有用。例如,您可能需要在给定时间插入多个事实,但需要决策引擎将插入操作视为原子操作,并等待所有插入完成,然后再重新评估规则。