ILOG JRules User Guide > Optimizing Execution > Tasks > Running Several Rule Engines in Parallel

Different instances of the same rule engine class may be required to process your data (multithreading), for various reasons that include:

ILOG JRules supports multithreading by using synchronization modifiers, and performs background garbage collection for multiple threads.

It is recommended that you synchronize your own application objects. For example, ILOG JRules allows multiple rule engines running in separate threads to share Java objects, and it allows several IlrContext objects running in different threads to share rulesets.

The illustration belows shows multithread architecture.

images/multithreading.png

The rule engines running in thread 1 and thread 3 use two synchronized objects, represented as a circle and a square. The engine in thread 1 has locked the square object and the engine in thread 3 has locked the circle object. The engines in thread 1 and thread 2 both have object calls that are waiting for the engine in thread 3 to relinquish its locked object, while the engine in thread 3 is waiting for thread 1 to finish with its shared object.

The ILOG JRules synchronized API elements are:

public synchronized void insert(Object o);
public synchronized void update(Object o);
public synchronized void update(Object o, boolean ref);
public synchronized void updateContext();
public synchronized void updateContext(boolean refresh);
public synchronized Enumeration enumerateObjects();
public synchronized void retract(Object o);
public synchronized void retractAll();
public synchronized IlrRuleInstance fireRule();
public synchronized int fireAllRules();

Different threads do not refer to each other automatically. You must use Java inlines to enable this communication. In addition, the IlrContext class behaves sequentially and respects the following rules:

The following code provides an example of a transfer from context1 to context2:

IlrContext context1 = new IlrContext();
IlrContext context2 = new IlrContext();
//context1 does its thing
loadDataIn(context1);
context1.fireAllRules();
//context1 transfers objects to context2
IlrRule r1 = context1.getRuleset().getRule("transferFilteredAlarms");
context1.fireRules(new IlrRule[] {r1});
//context2 does its thing
context2.fireAllRules();

The following rule transfers execution to the next IlrContext:

rule transferFilteredAlarms 
 {
   priority = high;
   when {
       ?al: Alarm(status == FILTERED);
    }
   then {
       ?context.successor.insert(?al);
       // whatever else ...
       ?context.successor.fireAllRules();
    }
 };

The responsibility for coordination falls upon the IlrContext classes themselves; an IlrContext in which an object is added must add it into another IlrContext.

This example is through the rules themselves:

rule insertInOthers { 
priority = default;
  when {
     ?la: LoanApplication();
  }
  then {
     IlrContext ?ctx = ?context.getOtherContext();
     {?ctx.insert(?la);}
  }
}

Warning
You must exercise caution to prevent programs from becoming blocked. A program can be blocked when a section of code cannot gain access to a limited resource. Two forms of blockage exist:

Multithreading is a powerful means of optimization. Threads are relatively cheap to create, run, and destroy. However, overuse of threads can be hazardous to your program performance and maintainability. Threads consume resources. Therefore, there is a limit on how many threads you can create without degrading performance.

Related Concepts

Java and ILOG JRules
What is XML Binding

Related Tasks

Executing a Ruleset Using a Native Rule Engine