【Design Pattern】Concurrency - Active Object Pattern

Posted by 西维蜀黍 on 2021-06-27, Last Modified on 2023-02-21

ACTIVE OBJECT

Active Object is a concurrency pattern in which we try to separate the invocation of a method from its execution. Typically, an active object provides synchronous methods and executes the method calls in an asynchronous way. An active object usually has its own thread of control.

This pattern is useful in refactoring legacy projects by introducing concurrency capability.

The following class diagram shows the basic structure of this pattern.

The key elements in active object pattern are:

  • Proxy (or Client Interface) - A public method provided by active object to clients.
  • Dispatch Queue - A list of pending requests from clients.
  • Scheduler - Determines the order to execute the requests.
  • Result Handle (or Callback) - This allows the result to be obtained by proxy after a request is executed.

Example

The following code shows an example of active object. The ActiveObject class uses a separate thread to execute the tasks.

import java.util.concurrent.PriorityBlockingQueue;

class ActiveObject {
  class Task implements Comparable < Task > {
    // smaller number means higher priority
    int priority;
    String name;
    Task(String name, int priority) {
      this.name = name;
      this.priority = priority;
    }
    public int compareTo(Task other) {
      return Integer.compare(this.priority, other.priority);
    }
  }
  private PriorityBlockingQueue < Task > dispatchQueue = new PriorityBlockingQueue < > ();
  public ActiveObject() {
    // A priority scheduler
    new Thread(() - > {
        while (true) {
          try {
            Task task = dispatchQueue.take();
            System.out.println("Executing task " + task.name);
          } catch (InterruptedException e) {
            break;
          }
        }
      })
      .start();
  }
  public void doTask(String name, int priority) {
    dispatchQueue.put(new Task(name, priority));
  }
}

In the above example, the dispatchQueue acts as both a dispatch queue and a scheduler. Of course we can separate the scheduler and the dispatch queue. The implementation is up to you.

To test the ActiveObject, we can create several threads calling doTask method at the same time, as shown in the following code.

// Testing ActiveObject
ActiveObject obj = new ActiveObject();
// Call doTask in different threads
Thread t1 = new Thread(() - > {
  obj.doTask("1", 2);
});
Thread t2 = new Thread(() - > {
  obj.doTask("2", 0);
});
Thread t3 = new Thread(() - > {
  obj.doTask("3", 1);
});
t1.start();
t2.start();
t3.start();

Reference