多线程将如何影响 Easy Rules 引擎?

How will multi-threading affect the Easy Rules engine?

我正在为我的 Web 应用程序寻找规则引擎,我找到了 Easy Rules。但是,在常见问题解答部分,它指出线程安全的限制。

Web 容器是否被视为多线程环境?对于 HTTP 请求,可能由应用程序服务器创建的工作线程处理。

线程安全是如何实现的?

How to deal with thread safety?

If you run Easy Rules in a multi-threaded environment, you should take into account the following considerations:

Easy Rules engine holds a set of rules, it is not thread safe.
By design, rules in Easy Rules encapsulate the business object model they operate on, so they are not thread safe neither.
Do not try to make everything synchronized or locked down! 

Easy Rules 引擎是一个非常轻量级的对象,您可以为每个线程创建一个实例,这是迄今为止避免线程安全问题的最简单方法

基于这个例子,多线程将如何影响规则引擎?

public class AgeRule extends BasicRule {
    private static final int ADULT_AGE = 18;

    private Person person;

    public AgeRule(Person person) {
        super("AgeRule",
              "Check if person's age is > 18 and
               marks the person as adult", 1);
        this.person = person;
    }

    @Override
    public boolean evaluate() {
        return person.getAge() > ADULT_AGE;
    }

    @Override
    public void execute() {
        person.setAdult(true);
        System.out.printf("Person %s has been marked as adult",
                            person.getName());
    }

}

public class AlcoholRule extends BasicRule {

    private Person person;

    public AlcoholRule(Person person) {
        super("AlcoholRule", 
              "Children are not allowed to buy alcohol",
               2);
        this.person = person;
    }

    @Condition
    public boolean evaluate() {
        return !person.isAdult();
    }

    @Action
    public void execute(){
        System.out.printf("Shop: Sorry %s,
                you are not allowed to buy alcohol",
                 person.getName());
    }

}

public class Launcher {

    public void someMethod() {
        //create a person instance
        Person tom = new Person("Tom", 14);
        System.out.println("Tom:
                Hi! can I have some Vodka please?");

        //create a rules engine
        RulesEngine rulesEngine = aNewRulesEngine()
                .named("shop rules engine")
                .build();

        //register rules
        rulesEngine.registerRule(new AgeRule(tom));
        rulesEngine.registerRule(new AlcoholRule(tom));

        //fire rules
        rulesEngine.fireRules();
    }

}

是的,Web 应用程序是多线程的。如您所料,服务器维护了一个线程池。当 serversocket 在它正在侦听的端口上收到传入请求时,它将请求委托给来自 pool.Typically 的线程,请求在该线程上执行,直到响应完成。

如果您尝试创建单个规则引擎并让多个线程访问它,那么

  1. 规则引擎数据由于被多个线程操纵而损坏(因为数据结构不是线程安全的,可以分多个步骤执行操作,这些步骤可能会被其他线程干扰,因为它们正在访问和更改相同的数据),或者

  2. 您使用锁定来确保一次只有一个线程可以使用规则引擎,避免您的共享对象被破坏,但在这个过程中造成了瓶颈。您的所有请求都需要等待规则引擎可用,并且一次只有一个线程可以取得进展。

最好为每个请求提供自己的规则引擎副本,这样它就不会损坏,也不需要锁定。线程的理想情况是每个线程都能够独立执行而不需要争用共享资源。