Example of ThreadPoolExecutor in Java

By Arvind Rai, March 11, 2013 | Modified on August 14, 2016
On this page we will provide example of ThreadPoolExecutor in java. ThreadPoolExecutor is a java concurrent API and has been introduced in JDK 1.5. ThreadPoolExecutor is a ExecutorService that executes submitted Runnable task. ThreadPoolExecutor is instantiated by passing core pool size, maximum pool size, idle thread alive time, time unit for alive time, BlockingQueue, ThreadFactory and RejectedExecutionHandler. When a new request arrives, a new thread is created by ThreadPoolExecutor to serve the request even if idle thread is there in pool. It happens till the ThreadPoolExecutor achieves given core pool size. Thread is created by using ThreadFactory. Idle thread alive time does not apply on idle threads if pool size is less than or equal to core pool size. Now if a request arrives and pool size is equal to core pool size then first idle thread will serve the request and if there is no idle thread only when a new thread is created up to the maximum thread pool size. When pool size is larger than core pool size then idle thread will die after given alive time to release the resources. No thread will be created if the pool size has reached up to the maximum pool size. Now if a request arrives and no thread is idle to serve the request, then all the subsequent request will go in queue. Once a thread from pool becomes idle, then request from queue will be served. If ThreadPoolExecutor is unable to serve the request due to some reason then it throws RejectedExecutionException. This request is handled by RejectedExecutionHandler.

Instantiate ThreadPoolExecutor

We can instantiate ThreadPoolExecutor using the following constructor where ThreadFactory and RejectedExecutionHandler are optional parameters and default values are Executors.defaultThreadFactory() and ThreadPoolExecutor.AbortPolicy respectively.
ThreadPoolExecutor(int corePoolSize,
                   int maximumPoolSize, 
                   long keepAliveTime, 
                   TimeUnit unit, 
                   BlockingQueue<Runnable> workQueue, 
                   ThreadFactory threadFactory, 
                   RejectedExecutionHandler handler) 
int corePoolSize : Defines the core pool size. For every new request a new thread is created up to the core pool size even if there are idle threads in pool.

int maximumPoolSize : When a request is made and all the threads in core pool size are busy then a new thread is created until it reached up the maximum pool size. After the maximum pool size, all the new request goes into queue.

long keepAliveTime: This is a waiting time for an idle thread to die. An idle thread dies after keepAliveTime only if the thread count is more than core pool size and less or equal to maximum core pool size.

TimeUnit unit: This is the time unit for keepAliveTime parameter.

BlockingQueue<Runnable> workQueue : It holds the task before it is executed. It will contain only Runnable task. BlockingQueue is a queue such that if a thread wants to fetch an element and queue is empty then thread will be blocked and wait till the element gets available in queue. In the same way while adding element if there is no space in queue, thread will be blocked and wait to get space available.

ThreadFactory threadFactory : This is optional parameter. Pass the user defined ThreadFactory using which ThreadPoolExecutor will create threads. By default Executors.defaultThreadFactory() is used.

RejectedExecutionHandler handler: This is optional parameter. ThreadPoolExecutor.execute() can reject new task in two scenarios.
1. Executor has been shutdown.
2. Executor uses finite bounds for work queue capacity as well as maximum threads and they are saturated.

The rejected task is handled by RejectedExecutionHandler using following policies.
ThreadPoolExecutor.AbortPolicy: It aborts the task and always throws RejectedExecutionException.
ThreadPoolExecutor.CallerRunsPolicy: It executes the rejected task itself.
ThreadPoolExecutor.DiscardPolicy: It simply drops the task.
ThreadPoolExecutor.DiscardOldestPolicy: In case when ThreadPoolExecutor.execute() has rejected the task because of finite bounds of work queue and maximum limit, this policy simply drops the task at the head of the work queue. The default policy is ThreadPoolExecutor.AbortPolicy.

Execute Task using ThreadPoolExecutor

ThreadPoolExecutor provides execute() method to run Runnable task some times in future. The task will run either by a thread in the pool or by new thread. If thread pool rejects the task then it will be handled by RejectedExecutionHandler. ThreadPoolExecutor can be inherited to provide custom definition for the methods beforeExecute() and afterExecute(). beforeExecute() is invoked before the given Runnable task is executed and afterExecute() is invoked upon the task completion.

Shutdown, Terminate and Remove Task in ThreadPoolExecutor

ThreadPoolExecutor provides the following methods to shutdown, terminate and remove the tasks.
shutdown(): When this method is called, ThreadPoolExecutor starts shutting down in the order in which previously submitted task executed and no new task is accepted. It does not wait to complete the execution of previously submitted task.
shutdownNow(): It stops all actively executing tasks and also halts the processing of waiting tasks and returns the list of waiting tasks. They are removed from the queue as well. This method does not wait to terminate the actively executing tasks.
awaitTermination(): This methods blocks the shutdown request until all tasks have completed or timeout occurs or thread is interrupted. We need to pass maximum waiting time.
isShutdown(): Returns true if executor has been shutdown.
isTerminated(): Returns true if all tasks have followed shutdown.
purge(): It tries to removes all tasks from the work queue that have been cancelled.
remove(): It removes the given task from the internal queue of executor.

ThreadPoolExecutor setMaximumPoolSize() and getMaximumPoolSize() Example

Maximum pool size for ThreadPoolExecutor is assigned while instantiating using constructor but we can change the value at runtime too using the method given below.
setMaximumPoolSize(): Sets maximum allowed number of threads at runtime.
getMaximumPoolSize(): Fetches the maximum allowed number of threads in pool.

ThreadPoolExecutorDemoOne.java
package com.concretepage;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExecutorDemoOne {
    public static void main(final String[] args) throws Exception {
        final ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 3, 100, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(), new ThreadPoolExecutor.CallerRunsPolicy());
        executor.execute(new BookReader("Ramayan"));
        executor.execute(new BookReader("Mahabharat"));
        executor.execute(new BookReader("Veda"));
        System.out.println("Old Max Pool Size:"+ executor.getMaximumPoolSize());
        executor.setMaximumPoolSize(4);
        System.out.println("New Max Pool Size:"+ executor.getMaximumPoolSize());        
        executor.shutdown();
    }
} 
BookReader.java
package com.concretepage;
public class BookReader implements Runnable {
	private String bookName;
	public BookReader(String bookName) {
		this.bookName = bookName;
	}
	@Override
	public void run() {
		for(int i = 0; i<3; i++) {
			System.out.println("Reading book: "+ bookName);
		}
	}
} 
Output
Reading book: Ramayan
Reading book: Ramayan
Reading book: Ramayan
Reading book: Veda
Reading book: Mahabharat
Reading book: Mahabharat
Reading book: Mahabharat
Old Max Pool Size:3
Reading book: Veda
Reading book: Veda
New Max Pool Size:4 

ThreadPoolExecutor setCorePoolSize(), getCorePoolSize() and getCompletedTaskCount() Example

Core pool size of work queue can also be changed at run time.
setCorePoolSize() : Sets new core pool size at run time.
getCorePoolSize() : Fetches core pool size.
getCompletedTaskCount() : Returns completed task count.

ThreadPoolExecutorDemoTwo.java
package com.concretepage;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExecutorDemoTwo {
    public static void main(final String[] args) throws Exception {
        final ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 100, TimeUnit.MILLISECONDS,
                 new LinkedBlockingQueue<Runnable>(), new MyThreadFactory(), 
                 new ThreadPoolExecutor.CallerRunsPolicy());
        executor.execute(new BookReader("Mantra"));
        executor.execute(new BookReader("Karbla"));
        executor.execute(new BookReader("Sipahi"));
        System.out.println("Completed Task:"+ executor.getCompletedTaskCount());
        System.out.println("Old Core Pool Size:"+ executor.getCorePoolSize());
        executor.setCorePoolSize(3);
        System.out.println("New Core Pool Size:"+ executor.getCorePoolSize());
        executor.shutdown();
    }
} 
MyThreadFactory.java
package com.concretepage;
import java.util.concurrent.ThreadFactory;
public class MyThreadFactory implements ThreadFactory {
	@Override
	public Thread newThread(Runnable r) {
		Thread t = new Thread(r);
		t.setPriority(Thread.MAX_PRIORITY );
		System.out.println("---Thread Created---");
		return t;
	}
} 
Output
---Thread Created---
---Thread Created---
Reading book: Mantra
Reading book: Karbla
Reading book: Mantra
Reading book: Mantra
Reading book: Karbla
Reading book: Sipahi
Reading book: Karbla
Reading book: Sipahi
Reading book: Sipahi
Completed Task:2
Old Core Pool Size:2
New Core Pool Size:3 
Though ThreadPoolExecutor provides many adjustable parameters, we should prefer to use Executors.newCachedThreadPool(), Executors.newFixedThreadPool(int) and Executors.newSingleThreadExecutor() over it.
POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us