Ever wondered how a file is attached to an e-mail in web-based mail applications such as Yahoo Mail, Gmail etc.? If you have been using Yahoo Mail for some years now, you might remember that not very long ago, when we used to add a file attachment to an e-mail, we had to keep waiting till the file was uploaded to the server. With the recent UI changes, when we attach a file, it gets added parallely while we perform other tasks on the UI. What has changed? The Active Object Pattern design pattern is working under the hood. If not implemented explicitly then the UI framework must be using it implicitly.
We had an application which read XML messages from message queue and parsed them. A single thread performed these operations. The messages were not related to each other and they were not needed to be parsed in the same sequence as they were stored in message queue. The messages would remain queued until the previous message was read and parsed. We decided to fasten the application by implementing Active Object Pattern.
The Active Object Pattern decouples the method invocation from method execution. The method invocation is made on an Active Object on client thread and method execution is performed by an independent thread asynchronously without blocking the client thread (Figure 1). Thus, the client thread is not tied-up until the method execution is over. After a method is invoked and the command to execute it is dispatched to the Scheduler or Dispatcher, it can perform other tasks.
The method is invoked on Active Object. An Active Object has a public interface called as Proxy. The Active Object creates a Message (Command pattern) which contains the information about the method call and puts it in the Message Queue. After the message is enqueued, the Scheduler or Dispatcher is notified to read the message. The Scheduler reads the message by dequeuing it from Message Queue. After the message is read, the Scheduler creates one or multiple threads called Servant for each method execution. The message sent by Scheduler is interpreted and executed by the Servant. The method may return a result as a Future implementation to the client.
Many variants of this design pattern are also in use. We have used a variant of this design pattern in our application (Figure 2). A thread pool creates Servants and a BlockingQueue implementation – LinkedBlockingQueue is used to store messages. The XML message and not the method information is added as a message in the queue. The Scheduler runs independently of the Active Object as a separate thread and there is no need to notify it when the message is added to the queue. The Scheduler reads the message from BlockingQueue. If the queue is empty, the Scheduler will keep waiting until the message is present in the queue. After reading the message from queue the Scheduler dispatches it to one of the Servant threads for parsing.
Whenever you have to perform independent tasks and a single thread is used for the entire task execution, do consider using this design pattern as it will enable concurrent execution of tasks, decreasing the execution time. The creation of multiple threads is an overhead but it is not significant considering the advantages this design pattern provides.