Code Pumpkin

Threadpool using Executor Framework | Java Concurrency Utilities

June 30, 2017
Posted by Pumpkin
Subscribe

The JDK 1.5 Executor framework is a combination of various Executor interfaces and Executors utility class to provide a thread pool feature in Java. 

In server side programming, Thread pool is an important concept to maintain scalability, robustness, and stability of the system.  

Thread pool is a pool of worker threads, which is ready to perform any task given to them, mostly in the form of implementation of Runnable or Callable interface.


Why do we need ThreadPool ?

In a large scale web application, if only one thread / process is used to process all client requests, then only one client can access the server at a time.  In order to support large number of clients, we need to use one thread per request paradigm i.e. we need to use separate threads to process each client request. But this require new threads to be created, when request arrived.

Creating a thread in java is a very expensive process which includes memory overhead. So, it’s a good idea if we can re-use these threads once created, to run our future runnables. Thread pool solves this problem for us. It creates Thread and manages them. Instead of creating Thread and discarding them once task is done, thread-pool reuses threads in form of worker thread. 


Executor framework

Java 1.5 introduced Thread pool in Java in the form of Executor framework, which allows Java programmer to decouple submission of a task to execution of the task.

java.util.concurrent package hierarchy :

Executor Framework


1) Executor

Executor interface is the core of executor framework. It has two sub interfaces ExecutorService and ScheduledExecutorService.  An object of type Executor can execute Runnable and Callable tasks.

Using an Executor it is possible to remove the manual creation of threads to execute a command. Given any Runnable implementation, like the following:


public class MyRunnable implements Runnable {
  public void run() {
    // code to be executed
  }
}

The following code with an explicit Thread creation:


Thread t = new Thread(new MyRunnable());
t.start();

can be replaced with the following code that instead uses an Executor:


Executor executor = ... // Executor creation
executor.execute(new MyRunnable());

void execute(Runnable command)

execute() method Executes the given command or Runnable task at some time in the future. The command may execute in a new thread, in a pooled thread, or in the calling thread, at the discretion of the Executor implementation.


2) Executors class

Executor framework also provides a static utility class called Executors ( similar to Collections) which provides several static factory method to create various type of Thread Pool implementation in Java e.g. fixed size thread pool, cached thread pool and scheduled thread pool

Though you can use ThreadPoolExecutor and ScheduledThreadPoolExecutor directly, but the best way to get an executor is to use one of the static factory methods provided by the Executors utility class. Some of the available factory methods in Executors class are:

  1.  static ExecutorService newCachedThreadPool() : Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available.
  2. static ExecutorService newFixedThreadPool(int numThreads) : Creates a thread pool that reuses a fixed number of threads.
  3. static ScheduledExecutorService newScheduledThreadPool(int numThreads) : Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically.
  4. newSingleThreadExecutor() : Creates an Executor that uses a single worker thread.

ExecutorService shutdown

An ExecutorService can be shut down, which will cause it to reject new tasks. Two different methods are provided for shutting down an ExecutorService.

  1. shutdown() method will allow previously submitted tasks to execute before terminating.
  2. shutdownNow() method prevents waiting tasks from starting and attempts to stop currently executing tasks.

Upon termination, an executor has no tasks actively executing, no tasks awaiting execution, and no new tasks can be submitted.  An unused ExecutorService should be shut down to allow reclamation of its resources.


fixed size thread pool Example

In this example a thread pool of two threads are created, and 6 runnable tasks are executed. These 6 tasks will be executed using only these 2 threads from the thread pool, new thread won't be created for each of the 6 tasks. It can be verified from the thread name in the output.


import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorDemo {
	public static void main(String args[]) {
		// creating executor with pool of 2 threads
		ExecutorService ex = Executors.newFixedThreadPool(2);
		// running 6 tasks
		ex.execute(new Task());
		ex.execute(new Task());
		ex.execute(new Task());
		ex.execute(new Task());
		ex.execute(new Task());
		ex.execute(new Task());
		// shutting down the executor service
		ex.shutdown();
	}
}

class Task implements Runnable {

	@Override
	public void run() {
		System.out.println("Thread - " + Thread.currentThread().getName());
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

Output


Thread - pool-1-thread-1
Thread - pool-1-thread-2
Thread - pool-1-thread-1
Thread - pool-1-thread-2
Thread - pool-1-thread-2
Thread - pool-1-thread-1

Benefits of Using the Thread Pool

  1. Better performance : Creating a brand new thread each time a new task arrives is expensive. Threadpool saves time because it re-uses the threads once created, to run future runnables.
  2. You do not have to create, manage, schedule, and terminate your thread, Executor framework does all of this for you. In other words, Thread Pool frees application developer from thread management stuff and allows to focus on business logic.
  3. Use of Threadpool allows you to change your execution policy as you need. you can go from single thread to multiple threads by just replacing ExecutorService implementation.

Limitations of Using the Thread Pool

While the thread pool is a powerful mechanism for structuring multithreaded applications, it is not without risk such as pool-related deadlock, resource thrashing and thread leakage. 

  1. Resource thrashing

    If the thread pool size is not tuned properly threads consume numerous resources, including memory and other system resources. While the scheduling overhead of switching between threads is small, with many threads context switching can become a significant drag on your program’s performance.

  2. Thread leakage

    A significant risk in all kinds of thread pools is thread leakage, which occurs when a thread is removed from the pool to perform a task, but is not returned to the pool when the task completes.

    One way this happens is when the task throws a RuntimeException or an Error. If the pool class does not catch these, then the thread will simply exit and the size of the thread pool will be permanently reduced by one.

    When this happens enough times, the thread pool will eventually be empty, and the system will stall because no threads are available to process tasks.

    While using Executor framework, we don't need to worry about thread leakages anymore.

Happy Learning smiley

Tags: , , , ,


Comments and Queries

If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code class="java"> 
String foo = "bar";
</code></pre>
For more information on supported HTML tags in disqus comment, click here.

Total Post : 80
Subscribe
Contribute Your Articles

Interview Experiences

Related Books

Like Us On Facebook

Alexa Page Rank