e-Zest members share technology ideas to foster digital transformation.

The Executor Framework – Part VI

Written by Madhura Oak | May 27, 2013 5:23:19 PM

In the last post of the Executor Framework blog post series, I had written about executing a single task from a collection of tasks, creating a Callable task from a Runnable task, cached Thread Pool and ThreadPoolExecutor.

ThreadPoolExecutor class implements ExecutorService interface.

In this blog post, I’m writing about the following topics related to ThreadPoolExecutor:

  • Changing RejectedExecutionHandler policy
  • Executing a Runnable task
  • Obtaining thread statistics
  • Obtaining task statistics
  • Defining work to be done before and after execution of each task
  • Monitoring the underlying task queue
  • Removing tasks from task queue

Changing RejectedExecutionHandler policy

When a bounded queue is used by ThreadPoolExecutor to hold the tasks submitted for execution and the queue is full, the following four RejectedExecutionHandler policies decide what happens to the tasks that are added to the queue after it becomes full:

  • ThreadPoolExecutor.AbortPolicy – This is the default policy. When the queue is full all tasks added to the queue are rejected and RejectedExecutionException is thrown.
  • ThreadPoolExecutor.CallerRunsPolicy – If this policy is applied the thread which called the execute() method of ThreadPoolExecutor, is used to run the task.
  • ThreadPoolExecutor.DiscardPolicy – The task is discarded without throwing any exception.
  • ThreadPoolExecutor.DiscardOldestPolicy – The task at the head of queue is removed from the queue.

The RejectedExecutionHandler can be changed by calling the setRejectedExecutionHandler(RejectedExecutionHandler handler) method of ThreadPoolExecutor.

Executing a Runnable task

The execute(Runnable command) method of ThreadPoolExecutor submits a Runnable task for execution. The method may execute it immediately or in future. The task may be executed by a new thread or an existing thread from the pool depending on the ThreadPoolExecutor configuration. If the task submitted for execution is rejected, then the configured RejectedExecutionHandler decides how the rejected task should be handled.

Obtaining thread statistics

The following methods of ThreadPoolExecutor enable obtaining thread statistics:

  • getActiveCount() - returns the number of threads actively executing tasks.
  • getCorePoolSize() – returns the count of core threads in the pool
  • getLargestPoolSize() – returns the maximum count of threads that concurrently existed in the pool
  • getMaxiumPoolSize() – return the maximum number of threads that can run concurrently in the pool.
  • getPoolSize() – returns the current count of threads in the pool

Obtaining task statistics

The following methods of ThreadPoolExecutor enable obtaining task statistics:

  • getCompletedTaskCount() – returns the count of tasks that are completed
  • getTaskCount() – returns the count of tasks that have ever been scheduled for execution

Defining work to be done before and after execution of each task

The beforeExecute(Thread, Runnable) method can be overridden to define the work that should be done before running each task. The work is defined as Runnable task which is the second argument and the thread which should perform it is passed as the first argument to this method.

The afterExecute(Runnable, Throwable) can be overridden to define the work that should be done after the task is executed. It is defined as Runnable task. If the task is terminated and an exception is thrown, it will be represented by the second argument. If the task completes normally then the second argument is null.

The terminated() method allows defining work that should be done after the ThreadPoolExecutor is terminated.

Monitoring the underlying task queue

The underlying task queue used by ThreadPoolExecutor can be accessed by getQueue() method. Direct usage of the queue except for monitoring purpose is discouraged.

Removing tasks from the task queue

The remove(Runnable task) method of ThreadPoolExecutor can be called to remove a task from the task queue. If the task is found in the task queue and it is not already running then it is removed from the task queue. This method returns true if the task is removed.

The purge() method of ThreadPoolExecutor tries to remove the cancelled Future tasks from the task queue. Cancelled tasks may be retained in the task queue until a worker thread removes them. This method helps to reclaim storage memory by trying to remove the cancelled tasks.