Executor Framework Java
A framework having a bunch of components that are used for managing worker threads efficiently is referred to as Executor Framework. The Executor API reduces the execution of the task from the actual task to be executed through the Executors. The executor framework is an implementation of the Producer-Consumer pattern. The java.util.concurrent.Executors class provides a set of methods for creating ThreadPools of worker threads.
In order to use the executor framework, we have to create a thread pool for executing the task by submitting that task to that thread pool.
Now, the question which comes to our mind is why we have to create such thread pools when we already have the java.lang.Thread class for creating an object and Runnable/Callable interface for achieving parallelism by implementing them. So, the reason for creating such thread pools are as follows:
Types of Executors
In Java, there are different types of executors available which are as follows:
The SingleThreadExecutor is a special type of executor that has only a single thread. It is used when we need to execute tasks in sequential order. In case when a thread dies due to some error or exception at the time of executing a task, a new thread is created, and all the subsequent tasks execute in that new one.
FixedThreadPool is another special type of executor that is a thread pool having a fixed number of threads. By this executor, the submitted task is executed by the n thread. In case when we need to execute more tasks after submitting previous tasks, they store in the LinkedBlockingQueue until previous tasks are not completed. The n denotes the total number of thread which are supported by the underlying processor.
The CachedThreadPool is a special type of thread pool that is used to execute short-lived parallel tasks. The cached thread pool doesn't have a fixed number of threads. When a new task comes at a time when all the threads are busy in executing some other tasks, a new thread creates by the pool and add to the executor. When a thread becomes free, it carries out the execution of the new tasks. Threads are terminated and removed from the cached when they remain idle for sixty seconds.
The ScheduledExecutor is another special type of executor which we use to run a certain task at regular intervals. It is also used when we need to delay a certain task.
The scheduleAtFixedRate and scheduleWithFixedDelay are the two methods that are used to schedule the task in ScheduledExecutor. The scheduleAtFixedRate method executes the task with a fixed interval when the previous task ended. The scheduleWithFixedDelay method starts the delay count after the current task complete. The main difference between these two methods is their interpretation of the delay between successive executions of a scheduled job. Both the methods are used in the following way:
Let's take an example to understand how executors are actually used to execute a task. We will simply create a task and try to execute it by the simple executor and ThreadPoolExecutor one by one.
Let's take an example of ThreadPoolExecutor to understand how it is different from the SimpleExecutor.
The RejectedExecutionHandlerDemo class is used for handling the jobs that are rejected from the worker queue. When the limit of the thread pool size reach, RejectedExecutionHandler handles those jobs that cannot fit in the worker thread. We will implement the RejectedExecutionHandler.java class in the following way:
We create the NewTask.java class to create a thread that monitors the executor and prints its information at a certain time interval. There are several methods available in the ThreadPoolExecutor class that is used to get the current state of the executor, number of active threads, number of tasks, and pool size. We create the monitor thread in the following way:
It is used to create the thread pool using the ThreadPoolExecutor.
Notice the change in the number of active threads, the number of the completed task, and the number of tasks. The shutdown() method is used to finish the execution of all the submitted tasks and terminate the thread pool.