,

Tuesday 5 August 2014

ThreadPool in java

ThreadPool is used when you want to restrict the number of threads and execute all the tasks using those threads. It has better performance as specific number of threads are started once and they execute the task , once the tasks are completed other tasks are assigned and executed by the same thread. So instead of creating as many threads as Runnable , it is better to start a specific number of threads at one time and the execute all the tasks accordingly.
In the below program , tasks are added to LinkedList which are executed by the threads. The LinkedList is used to enqueue and deque the tasks.

Note: To keep the code simple , minimum functionality is added so that the Runnables are added and executed by the thread-pool

TestThreadPool is the class which has the main function. It instantiates the thread-pool with the number of threads. In the main function we are creating 10 tasks and adding these tasks to the thread-pool.

Demo 1:
//file TestThreadPool.java
package com.i;
/**
 * 
 * @author Ganesh.Rashinker
 * 
 */

// class with main function
public class TestThreadPool {

public static void main(String[] args) {

// starting the number of threads
MyThreadPool threadPool = new MyThreadPool(2);
// creating 10 tasks and adding in thread pool
for (int i = 1; i <= 10; i++) {
MyTask task = new MyTask(i);
threadPool.doTask(task);
}

// when task completed , two threads are still waiting
threadPool.join();
}
}

MyTask is a class which implements Runnable. These would be the tasks added and executed by the threadpool.
//file MyTask.java
package com.i;
/**
 * 
 * @author Ganesh.Rashinker
 * 
 */

public class MyTask implements Runnable {

private int taskNo;

public MyTask(int taskNo) {
super();
this.taskNo = taskNo;
}

@Override
public void run() {
System.out.println("started the task: " + taskNo);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ended the task: " + taskNo);
}
}

MyThreadPool is the basic threadpool implementation which takes care of starting the number of threads and executing all the tasks using these threads. MyWorkerThread is the worker thread of threadpool which does the task of executing the runnable tasks.
//file MyThreadPool.java
package com.i;
import java.util.LinkedList;
/**
 * 
 * @author Ganesh.Rashinker
 * 
 */

//ThreadPool class using ThreadGroup
public class MyThreadPool extends ThreadGroup {

private boolean isAlive;

private LinkedList<Runnable> queue;

public MyThreadPool(int numThreads) {
super("ThreadPool");
isAlive = true;
queue = new LinkedList<Runnable>();
for (int i = 0; i < numThreads; i++) {
// starting WorkerThreads
new MyWorkerThread().start();
}
}

// adding tasks
public synchronized void doTask(Runnable task) {
queue.add(task);
notify();
}

// returns/gives the task to WorkerThread
protected synchronized Runnable giveTask() {
while (queue.size() == 0) {
if (!isAlive) {
return null;
}
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return (Runnable) queue.removeFirst();
}

// join function to notify all waiting threads
public void join() {
synchronized (this) {
isAlive = false;
notifyAll();
}
Thread[] threads = new Thread[activeCount()];
int threadNo = enumerate(threads);
for (int i = 0; i < threadNo; i++) {

try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

// WorkerThread class
private class MyWorkerThread extends Thread {

public void run() {
while (!isInterrupted()) {
Runnable task = giveTask();
if (task == null) {
return;
}
// running/executing the task
task.run();
}
}
}
}

Conclusion: Using thread-pool is efficient as the specific number of threads are started once , which executes the tasks one after the other on the basis of their availability. This approach is better than creating individual threads for each Runnable.

No comments:

Post a Comment