我发现了drools引擎的奇怪行为 . 我有两个不同突出的规则 . 如drools文档中所述
3.3.4.1 . 冲突解决当议程上有多个规则时,需要解决冲突 . (“快速入门”一章中介绍了基本知识 . )由于触发规则可能会对工作内存产生副作用,规则引擎需要知道规则应该以什么顺序触发(例如,触发规则A可能会导致规则B)被从议程中删除) . Drools采用的默认冲突解决策略是:Salience和LIFO(后进先出) . 最明显的是显着性(或优先级),在这种情况下,用户可以指定某个规则具有比其他规则更高的优先级(通过赋予它更高的数字) . 在这种情况下,具有较高显着性的规则将是优选的 . LIFO优先级基于分配的工作内存操作计数器值,在同一操作期间创建的所有规则都接收相同的值 . 具有相同优先级值的一组点火的执行顺序是任意的 .
但是为每种类型执行我的两个规则,每个类型有5个对象,这会产生奇怪的结果 - 在某些对象上,带有显着性的规则1比具有显着性的规则10更早执行 . 如果我从规则中删除更新,则首先执行具有显着性的规则10,然后才执行有突出性1 .
package com.sample
import com.sample.DroolsTest.Message;
import com.sample.DroolsTest.Message2;
rule "Hello World2"
salience 10
when
m : Message()
m2 : Message2(status <0)
then
System.out.println( "Second Rule With Salience 10");
System.out.println( "m status = "+m.getStatus());
System.out.println( "m2 status = "+m2.getStatus());
m2.setStatus(m2.getStatus()*(-1));
update(m2);
end
rule "Hello World3"
salience 1
when
m2 : Message2()
m : Message()
then
System.out.println( "Third Rule With Salience 1");
System.out.println( "m status = "+m.getStatus());
System.out.println( "m2 status = "+m2.getStatus());
end
rule "GoodBye"
salience 0
when
eval(true)
then
System.out.println( "End" );
end
这里是java代码,可以让你更快地测试它
package com.sample;
import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderErrors;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.ResourceFactory;
import org.drools.logger.KnowledgeRuntimeLogger;
import org.drools.logger.KnowledgeRuntimeLoggerFactory;
import org.drools.runtime.StatefulKnowledgeSession;
/**
* This is a sample class to launch a rule.
*/
public class DroolsTest {
public static final void main(String[] args) {
try {
// load up the knowledge base
KnowledgeBase kbase = readKnowledgeBase();
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
// go !
System.out.println("Start");
for(int i=0; i<5; i++){
Message message = new Message(i);
ksession.insert(message);
Message2 message2 = new Message2(-i);
ksession.insert(message2);
}
ksession.fireAllRules();
logger.close();
} catch (Throwable t) {
t.printStackTrace();
}
}
private static KnowledgeBase readKnowledgeBase() throws Exception {
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("Sample.drl"), ResourceType.DRL);
KnowledgeBuilderErrors errors = kbuilder.getErrors();
if (errors.size() > 0) {
for (KnowledgeBuilderError error: errors) {
System.err.println(error);
}
throw new IllegalArgumentException("Could not parse knowledge.");
}
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
return kbase;
}
public static class Message {
private int status;
public int getStatus() {
return this.status;
}
public Message(int status) {
super();
this.status = status;
}
public void setStatus(int status) {
this.status = status;
}
}
public static class Message2 {
private int status;
public Message2(int status) {
this.status = status;
}
public int getStatus() {
return this.status;
}
public void setStatus(int status) {
this.status = status;
}
}
}
谢谢,非常感谢你的帮助 . PS:我知道,依靠规则射击的顺序并不是一个好主意,但在我遇到这个之前,突显似乎值得信赖 .
1 回答
查看你的drl文件,你给出条件“when”part m2:Message2(status <0),请记住,LHS仅在断言时或在调用给定事实的modify()/ update()时进行评估 . 因此,在断言时,条件将评估为真并激活规则 . 你永远不会在同一个object.Message2上调用modify()/ update,因此,你的条件永远不会被重新评估 . 这就是为什么你会得到奇怪的行为 . 这就是为什么你会在没有更新的情况下得到理想的行为 .