Java ExecutorService

The java.util.concurrent.ExecutorService interface represents an asynchronous execution mechanism which is capable of executing tasks in the background. An ExecutorService is thus very similar to a thread pool. In fact, the implementation of ExecutorService present in the java.util.concurrent package is a thread pool implementation.


ExecutorService Example


Here is a simple Java ExectorService example:

ExecutorService executorService = Executors.newFixedThreadPool(10);

executorService.execute(new Runnable() {
    public void run() {
        System.out.println("Asynchronous task");
    }
});


executorService.shutdown();



First an ExecutorService is created using the newFixedThreadPool() factory method. This creates a thread pool with 10 threads executing tasks.
Second, an anonymous implementation of the Runnable interface is passed to the execute() method. This causes the Runnable to be executed by one of the threads in the ExecutorService.


Task Delegation


Here is a diagram illustrating a thread delegating a task to an ExecutorService for asynchronous execution:




Once the thread has delegated the task to the ExecutorService, the thread continues its own execution independent of the execution of that task.


ExecutorService Implementations


Since ExecutorService is an interface, you need to its implementations in order to make any use of it. The ExecutorService has the following implementation in the java.util.concurrent package:

ThreadPoolExecutor
ScheduledThreadPoolExecutor


Creating an ExecutorService


How you create an ExecutorService depends on the implementation you use. However, you can use the Executors factory class to create ExecutorService instances too. Here are a few examples of creating an ExecutorService:

ExecutorService exSer1 = Executors.newSingleThreadExecutor();

ExecutorService exSer2 = Executors.newFixedThreadPool(10);


ExecutorService exSer3 = Executors.newScheduledThreadPool(10);





ExecutorService Usage


There are a few different ways to delegate tasks for execution to an ExecutorService:

execute(Runnable)
submit(Runnable)
submit(Callable)
invokeAny(...)
invokeAll(...)

I will take a look at each of these methods in the following sections.



execute(Runnable)



The execute(Runnable) method takes a java.lang.Runnable object, and executes it asynchronously. Here is an example of executing a Runnable with an ExecutorService:

ExecutorService executorService = Executors.newSingleThreadExecutor();

executorService.execute(new Runnable() {
    public void run() {
        System.out.println("Asynchronous task");
    }
});


executorService.shutdown();



There is no way of obtaining the result of the executed Runnable, if necessary. You will have to use a Callable for that (explained in the following sections).

submit(Runnable)


The submit(Runnable) method also takes a Runnable implementation, but returns a Future object. This Future object can be used to check if the Runnable as finished executing.

Here is a ExecutorService submit() example:


Future future = executorService.submit(new Runnable() {
    public void run() {
        System.out.println("Asynchronous task");
    }
});

future.get();  //returns null if the task has finished correctly.



submit(Callable)


The submit(Callable) method is similar to the submit(Runnable) method except for the type of parameter it takes. The Callable instance is very similar to a Runnable except that its call() method can return a result. The Runnable.run() method cannot return a result.


The Callable's result can be obtained via the Future object returned by the submit(Callable) method. Here is an ExecutorService Callable example:


Future future = executorService.submit(new Callable(){
    public Object call() throws Exception {
        System.out.println("Asynchronous Callable");
        return "Callable Result";
    }
});


System.out.println("future.get() = " + future.get());


The above code example will output this:

Asynchronous Callable
future.get() = Callable Result


invokeAny()


The invokeAny() method takes a collection of Callable objects, or subinterfaces of Callable. Invoking this method does not return a Future, but returns the result of one of the Callable objects. You have no guarantee about which of the Callable's results you get. Just one of the ones that finish.

If one of the tasks complete (or throws an exception), the rest of the Callable's are cancelled.

Here is a code example:

ExecutorService executorService = Executors.newSingleThreadExecutor();

Set<Callable<String>> callables = new HashSet<Callable<String>>();

callables.add(new Callable<String>() {
    public String call() throws Exception {
        return "Task 1";
    }
});
callables.add(new Callable<String>() {
    public String call() throws Exception {
        return "Task 2";
    }
});
callables.add(new Callable<String>() {
    public String call() throws Exception {
        return "Task 3";
    }
});

String result = executorService.invokeAny(callables);

System.out.println("result = " + result);

executorService.shutdown();


This code example will print out the object returned by one of the Callable's in the given collection. I have tried running it a few times, and the result changes. Sometimes it is "Task 1", sometimes "Task 2" etc.


invokeAll()


The invokeAll() method invokes all of the Callable objects you pass to it in the collection passed as parameter. The invokeAll() returns a list of Future objects via which you can obtain the results of the executions of each Callable.

Keep in mind that a task might finish due to an exception, so it may not have "succeeded". There is no way on a Future to tell the difference.

Here is a code example:


ExecutorService executorService = Executors.newSingleThreadExecutor();

Set<Callable<String>> callables = new HashSet<Callable<String>>();

callables.add(new Callable<String>() {
    public String call() throws Exception {
        return "Task 1";
    }
});
callables.add(new Callable<String>() {
    public String call() throws Exception {
        return "Task 2";
    }
});
callables.add(new Callable<String>() {
    public String call() throws Exception {
        return "Task 3";
    }
});

List<Future<String>> futures = executorService.invokeAll(callables);

for(Future<String> future : futures){
    System.out.println("future.get = " + future.get());
}

executorService.shutdown();


ExecutorService Shutdown

When you are done using the ExecutorService you should shut it down, so the threads do not keep running.

For instance, if your application is started via a main() method and your main thread exits your application, the application will keep running if you have an active ExexutorService in your application. The active threads inside this ExecutorService prevents the JVM from shutting down.

To terminate the threads inside the ExecutorService you call its shutdown() method. The ExecutorService will not shut down immediately, but it will no longer accept new tasks, and once all threads have finished current tasks, the ExecutorService shuts down. All tasks submitted to the ExecutorService before shutdown() is called, are executed.

If you want to shut down the ExecutorService immediately, you can call the shutdownNow() method. This will attempt to stop all executing tasks right away, and skips all submitted but non-processed tasks. There are no guarantees given about the executing tasks. Perhaps they stop, perhaps the execute until the end. It is a best effort attempt.

Builder Pattern

The more complex an application is the complexity of classes and objects used increases. Complex objects are made of parts produced by other objects that need special care when being built. An application might need a mechanism for building complex objects that is independent from the ones that make up the object. If this is the problem you are being confronted with, you might want to try using the Builder (or Adaptive Builder) design pattern.
This pattern allows a client object to construct a complex object by specifying only its type and content, being shielded from the details related to the objects representation. This way the construction process can be used to create different representations. The logic of this process is isolated form the actual steps used in creating the complex object, so the process can be used again to create a different object form the same set of simple objects as the first one.

Builder Pattern Intent is:

Defines an instance for creating an object but letting subclasses decide which class to instantiate
Refers to the newly created object through a common interface


The participants classes in this pattern are:
The Builder class specifies an abstract interface for creating parts of a Product object.




The ConcreteBuilder constructs and puts together parts of the product by implementing the Builder interface. It defines and keeps track of the representation it creates and provides an interface for saving the product.
The Director class constructs the complex object using the Builder interface.
The Product represents the complex object that is being built.
The client, that may be either another object or the actual client that calls the main() method of the application, initiates the Builder and Director class. The Builder represents the complex object that needs to be built in terms of simpler objects and types. The constructor in the Director class receives a Builder object as a parameter from the Client and is responsible for calling the appropriate methods of the Builder class. In order to provide the Client with an interface for all concrete Builders, the Builder class should be an abstract one. This way you can add new types of complex objects by only defining the structure and reusing the logic for the actual construction process. The Client is the only one that needs to know about the new types, the Director needing to know which methods of the Builder to call.



The Client needs to convert a document from RTF format to ASCII format. There for, it calls the method createASCIIText that takes as a parameter the document that will be converted. This method calls the concrete builder, ASCIIConverter, that extends the Builder, TextConverter, and overrides its two methods for converting characters and paragraphs, and also the Director, RTFReader, that parses the document and calls the builders methods depending on the type of token encountered. The product, the ASCIIText, is built step by step, by appending converted characters.

//Abstract Builder
class abstract class TextConverter{
 abstract void convertCharacter(char c);
 abstract void convertParagraph();
}

// Product
class ASCIIText{
 public void append(char c){ //Implement the code here }
}

//Concrete Builder
class ASCIIConverter extends TextConverter{
 ASCIIText asciiTextObj;//resulting product

 /*converts a character to target representation and appends to the resulting*/
 object void convertCharacter(char c){
  char asciiChar = new Character(c).charValue();
   //gets the ascii character
  asciiTextObj.append(asciiChar);
 }
 void convertParagraph(){}
 ASCIIText getResult(){
  return asciiTextObj;
 }
}

//This class abstracts the document object
class Document{
 static int value;
 char token;
 public char getNextToken(){
  //Get the next token
  return token;
 }
}

//Director
class RTFReader{
 private static final char EOF='0'; //Delimitor for End of File
 final char CHAR='c';
 final char PARA='p';
 char t;
 TextConverter builder;
 RTFReader(TextConverter obj){
  builder=obj;
 }
 void parseRTF(Document doc){
  while ((t=doc.getNextToken())!= EOF){
   switch (t){
    case CHAR: builder.convertCharacter(t);
    case PARA: builder.convertParagraph();
   }
  }
 }
}

//Client
public class Client{
 void createASCIIText(Document doc){
  ASCIIConverter asciiBuilder = new ASCIIConverter();
  RTFReader rtfReader = new RTFReader(asciiBuilder);
  rtfReader.parseRTF(doc);
  ASCIIText asciiText = asciiBuilder.getResult();
 }
 public static void main(String args[]){
  Client client=new Client();
  Document doc=new Document();
  client.createASCIIText(doc);
  system.out.println("This is an example of Builder Pattern");
 }
}

 

Applicability & Examples

Builder Pattern is used when:
the creation algorithm of a complex object is independent from the parts that actually compose the object the system needs to allow different representations for the objects that are being built.



Example 1 - Vehicle Manufacturer.


Let us take the case of a vehicle manufacturer that, from a set of parts, can build a car, a bicycle, a motorcycle or a scooter. In this case the Builder will become the VehicleBuilder. It specifies the interface for building any of the vehicles in the list above, using the same set of parts and a different set of rules for every type of type of vehicle. The ConcreteBuilders will be the builders attached to each of the objects that are being under construction. The Product is of course the vehicle that is being constructed and the Director is the manufacturer and its shop.

Example 1 - Students Exams.


If we have an application that can be used by the students of a University to provide them with the list of their grades for their exams, this application needs to run in different ways depending on the user that is using it, user that has to log in. This means that, for example, the admin needs to have some buttons enabled, buttons that needs to be disabled for the student, the common user. The Builder provides the interface for building form depending on the login information. The ConcreteBuilders are the specific forms for each type of user. The Product is the final form that the application will use in the given case and the Director is the application that, based on the login information, needs a specific form.


Specific problems and implementation


Builder and Abstract Factory


The Builder design pattern is very similar, at some extent, to the Abstract Factory pattern. Thats why it is important to be able to make the difference between the situations when one or the other is used. In the case of the Abstract Factory, the client uses the factorys methods to create its own objects. In the Builders case, the Builder class is instructed on how to create the object and then it is asked for it, but the way that the class is put together is up to the Builder class, this detail making the difference between the two patterns.


Common interface for products


In practice the products created by the concrete builders have a structure significantly different, so if there is not a reason to derive different products a common parent class. This also distinguishes the Builder pattern from the Abstract Factory pattern which creates objects derived from a common type.