<img alt="" src="https://secure.leadforensics.com/150446.png " style="display:none;">
Go to top icon

The Executor Framework – Part I

Madhura Oak Feb 11, 2013

Executor Executors.newSingleThreadExecutor Runnable Java ExecutorService Thread fixed size thread pool single thread executor Multithreading Concurrency API Executors.newFixedSizeThreadPool Executors Technology

Multithreading is one of the important features of Java programming language. A thread runs a task and thus multiple threads enable execution of multiple tasks concurrently in a Java application. Prior to Java 5, Thread class was instantiated explicitly to create a thread. The thread pool implementation also was not provided by the API.

With the Concurrency API introduced in Java 5, there is no more need to explicitly instantiate Thread class to create a thread. The Executor framework included in the Concurrency API provides many facilities for multithreaded programming such as creating threads, creating various types of thread pools, submitting tasks to a thread pool, performing asynchronous execution of tasks etc.

It is recommended to use the Executor framework instead of using the Thread class directly in the code. The Executor framework allows decoupling of the code to create thread pool and threads and the code for tasks which the threads should execute. The former part is now taken care by the Concurrency API.

In one of my previous blog posts on Active Object Pattern, I had written about how we had used it to read the messages from the message queue (MQ) and parse them. We had used Executors to create a thread pool. A thread from the pool parsed a message and thus messages were parsed concurrently. The use of Executor framework saved the effort of writing code to create threads and managing a thread pool.

I’ll be writing about the Executor framework in a series of blog posts. In this blog post I have explained the following uses of the framework:

  1. Creating a single worker thread for sequential execution of tasks.
  2. Creating a thread pool of fixed number of threads.

The Concurrency API provides Executor, ExecutorService and ScheduledExecutorService interfaces. An instance of class implementing Executor is used to submit a Runnable task for execution instead of explicitly creating threads with Thread class. The ExecutorService is a subinterface of Executor.

ExecutorService allows submission of Callable tasks for asynchronous execution and creating cancellable Runnable tasks. Callable is an interface like Runnable and it is part of Concurrency API. The factory class - Executors of Concurrency API is generally used to obtain the implementation of ExecutorService and submit the Runnable or Callable tasks for execution.

Executing tasks sequentially with a single thread

The Executors.newSingleThreadExecutor() method returns an ExecutorService which uses a single worker thread to execute the Runnable or Callable tasks. An unbounded queue is used to held the tasks submitted to it which means that there is no upper limit on the number of tasks submitted for execution. The tasks are executed sequentially in the order of submission. Since only one thread is running them only one task will be running at a time. One advantage of using this factory method is that if the thread terminates due to an exception during execution of a task before shutdown of the ExecutorService, a new thread will be created and it will resume execution of the subsequent tasks.

The use of Executors.newSingleThreadExecutor() is given below in Listing 2. To illustrate the use of this method, I have used a simple Runnable task given in Listing 1. which prints Hello.

public class PrintHello implements Runnable {
    public void run() {
        System.out.println(“Hello”);
    }
}

Listing 1. A simple Runnable task to print Hello

 

ExecutorService service = Executors.newSingleThreadExecutor();
PrintHello task = new PrintHello();
//print Hello twice
service.execute(task);
service.execute(task);
service.shutdown();

Listing 2. Using the Executors.newSingleThreadExecutor() to run the task

Shutting down ExecutorService

The shutdown() method of ExecutorService should be explicitly called to stop it. It shuts down the ExecutorService after all the submitted tasks are executed. This method does not throw any exception if the ExecutorService has already stopped. The isShutdown() method of ExecutorService can be called to check whether it is stopped.

The shutdownNow() method of ExecutorService attempts to shutdown by stopping all active tasks in execution and cancelling all the waiting tasks. The list of Runnable tasks that were waiting for execution is returned by this method. This method does not guarantee stopping of active tasks. The active tasks are stopped by thread interrupt. If a thread is not interrupted the task may not stop.

Creating a thread pool with fixed number of threads

The Executors.newFixedSizeThreadPool(int n) creates a thread pool of n number of threads and returns an ExecutorService. This thread pool uses an unbounded queue which means that any number of tasks can be submitted to it for execution. This method may create all the threads at once or may create them as they are required. At max n number of threads will be active at any point during its execution. If more number of tasks are submitted than the number of active threads, then the remaining tasks will be held in the queue. As soon as a thread completes execution of a task, it can take over the execution of the waiting task from the queue.

For performance tuning, the number of threads to be created by the thread pool is usually defined in a properties file.

Listing 3 given below illustrates the creation of a thread pool and submitting tasks to it for execution.

//Read this value from a properties file
int thread_count = 2;
ExecutorService service =
        Executors.newFixedSizeThreadPool(thread_count);
PrintHello task = new PrintHello();
//print Hello 10 times
for(int i=1; i <=10; i++)
    service.execute(task);
}
service.shutdown();

Listing 3. Creating a thread pool of multiple threads and submitting the task for execution

Similar Blog

Relational databases have been around us for more than 20 years now. Needless to say, they are mature and an obvious choice for ...

By Madhura Oak Dec 24, 2013

Isolation of data in a session is the trickiest part of session management. A session may constitute of multiple requests. ...

By Madhura Oak Dec 02, 2013

There are three ways of session management in n-tier applications:

By Madhura Oak Nov 27, 2013

Performance is one of the non-functional requirements of an application. It defines the acceptable maximum response time for ...

By Madhura Oak Nov 25, 2013

While using multiple inheritance in domain model design you need to be cautious as programming languages such as Java do not ...

By Madhura Oak Nov 13, 2013

e-Zest is a leading digital innovation partner for enterprises and technology companies that utilizes emerging technologies for creating engaging customers experiences. Being a customer-focused and technology-driven company, it always helps clients in crafting holistic business value for their software development efforts. It offers software development and consulting services for cloud computing, enterprise mobility, big data and analytics, user experience and digital commerce.