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();Active 模式 :如果用户或应用程序调用
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() 调用,特别是从不同的线程中,决策引擎可以安全地使用 thread-safety 逻辑和内部状态机处理这种情况。如果 fireAllRules() 调用正在进行中,并且调用 fireUntilHalt(),则决策引擎将继续以被动模式运行,直到 fireAllRules() 操作完成,然后以主动模式开始响应 fireUntilHalt() 调用。但是,如果决策引擎在活跃的模式下运行,且调用 fireAllRules() 调用,并且您调用 调用将被忽略,则决策引擎将继续以活跃模式运行,直到调用 fireAllRules() halt()。
对于以活跃模式添加的线程安全,决策引擎支持 提交() 方法,您可以在线程安全、atomic 操作中对 KIE 会话执行操作:
带有 submit() 方法的示例应用程序代码,可在主动模式下执行 atomic 操作
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();
从客户端角度而言,线程安全和原子操作也很有帮助。例如,您可能需要在给定时间插入多个事实,但需要将决策引擎视为原子操作,并等待所有插入操作再次评估规则。