我是 Drools 的新手,已经阅读了一些文档和教程,当然,我的问题有一个简单的解决方案。 我仅使用规则文件和类 Counter,如下所示。环境是:Wintel JDK 1.7(71),DROOLS 6.1.0
public class DroolsInsertionTester {
private Logger log = Logger.getLogger(this.getClass().getName());
private KieSession getNewStatefullKIESession (){
KieContainer kContainer = KieServices.Factory.get().getKieClasspathContainer();
KieSession kSession = kContainer.newKieSession("test");
return kSession;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
DroolsInsertionTester tester = new DroolsInsertionTester();
tester.test();
}
private void test() {
KieSession kSession = getNewStatefullKIESession();
Counter cnt1 = new Counter(1);
Counter cnt2 = new Counter(2);
FactHandle fact1, fact2;
// STEP 1
fact1 = kSession.insert(cnt1);
kSession.fireAllRules();
// STEP 2
fact2 = kSession.insert(cnt2);
kSession.fireAllRules();
}
public class Counter {
public int count;
public Counter (int cnt){
this.count = cnt;
}
有一个规则
rule "Counter shower 1"
when $Counter : Counter()
then
System.out.println("Counter there (1) : " + $Counter.count);
end
rule "Counter shower 2"
when
$Counter : Counter()
accumulate (Counter() ; $cnt : count())
then
System.out.println("Counter there (2) : " + $Counter.count);
end
rule "Counter shower 3"
when
Counter()
then
System.out.println("Counters there (3) : ");
end
rule "Counter creator"
when $Counter : Counter(count == 2)
then
insert (new Counter(3)); // STEP 3
System.out.println("new Counter created ");
end
rule "Counter remover"
when
$Counter : Counter(count == 1)
exists Counter (count == 3)
then
retract ($Counter) ; // STEP 4
System.out.println("retract counter with ID = 1");
end
这是 kModule
<?xml version="1.0" encoding="UTF-8" ?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
<kbase name="rules" packages="rules">
<ksession name="test" />
</kbase>
</kmodule>
运行结果
Counter there (1) : 1
Counter there (2) : 1
Counters there (3) :
Counter there (1) : 2
Counter there (2) : 1
Counter there (2) : 2
Counters there (3) :
new Counter created
Counter there (1) : 3
Counter there (2) : 1
Counter there (2) : 2
Counter there (2) : 3
Counters there (3) :
retract counter with ID = 1
Counter there (2) : 2
Counter there (2) : 3
我的问题是:
程序代码不包含任何“kSession.delete”,所有事实都保存在工作内存中。因此,在我看来,规则“Counter Shower 1”..“Counter Shower 3”应该在每次 fireAllRules 调用后为工作内存中的每个 Counter 对象触发。 STEP 1 一次,STEP2 两次,STEP3 三次但输出列表指出只有“柜台淋浴 2”以这种方式工作。 “柜台淋浴 1”和“柜台淋浴 3”仅通过一次 fireAllRules 调用触发一次。
为什么规则“柜台淋浴 1”仅捕获最后插入的事实?其中是否存在隐藏行为?
3.为什么在收回计数== 1的对象计数器后仅“Counter Shower 2”触发?其他规则呢?
感谢您的帮助。
最佳答案
问题 1:程序代码不包含任何“kSession.delete”,所有事实都保存在工作内存中。因此,在我看来,规则“Counter Shower 1”..“Counter Shower 3”应该在每次 fireAllRules 调用后为工作内存中的每个 Counter 对象触发。 STEP 1 一次,STEP2 两次,STEP3 三次但输出列表指出只有“柜台淋浴 2”以这种方式工作。 “柜台淋浴 1”和“柜台淋浴 3”仅由一次 fireAllRules 调用触发一次。
您应该了解 fireAllRules
实际上并不会触发您知识库中的所有规则。这个名字有点误导。 :)
与其谈论规则“触发”,不如将其称为“激活”。您有一个有状态 session ,因此当您第一次调用 fireAllRules
时,您的三个规则将根据您最初插入的 Counter
激活。当您再次调用 insert
/fireAllRules
时,这些规则仍会针对初始 Counter
激活!他们不需要再次激活。除非工作内存的状态发生变化导致规则停用和重新激活,否则您将看不到右侧发生任何事情。
这实际上是有状态 session 的全部要点。您的知识库可以逐步“学习”事实,并可以根据现有知识评估新事实。
无状态 session 的目的是从零知识的假设中评估每个事实。
问题 2:为什么规则“柜台淋浴 1”仅捕获最后插入的事实?
您有一个有状态 session ,因此在第一个 fireAllRules
上激活 Counter
初始插入的匹配。从那时起,工作内存中没有发生任何影响初始激活的变化,因此当您再次 fireAllRules
时,它不再需要激活。
问题 3:为什么在收回对象 Counter 且 count == 1 后,仅“Counter Shower 2”触发?其他规则呢?
“Counter Shower 2”规则是唯一受撤回影响的规则,因为它有一个累加器对您的 Counter
事实进行计数。
关于java - Drools 中的工作内存和对象插入行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26420666/