ThreadPools are useful when a number of tasks needs to be executed . Dynamically we can create new threads for each tasks.But it is not feasible for the JVM to manage all these threads. In such situations a pool of threads can be used. This limits the maximum number of threads within a a limit. So it is easy for the JVM to manage the threads . Either we can create our own threadpool or we can use the ThreadPoolExecutor in java.util.concurrent .
ThreadPoolExecutor in java
A ThreadPoolExecutor in java manages a number of pooled threads . Assume there are a number of tasks to be executed . These tasks can be given to the ThreadPoolExecutor and each task will be executed by a thread in the thread pool. For more details about ThreadPoolExecutor ,please see the Java doc .
Usually the tasks to be taken by any of the threads in the pool are storing in a BlockingQueue . If all the threads are busy with tasks , then the new task is storing in this queue. When a thread is free it can take task from the queue.
ThreadPoolExecutor in java example
Now let us discuss this with an example.Here ,we have four tasks .
1)First task is printing multiples of 10 from 1 to 50 with an interval of 5 seconds
2)Second task is printing multiples of 10 from 50 to 100 with an interval of 5 seconds
3)Third task is printing multiples of 5from 100 to 150 with interval of 5 seconds
4)Fourth task is printing multiples of 10 from 150 to 200 with an interval of 5seconds
See the code snippet shown below. We are creating four runnable tasks . And then creating a new thread pool executor with core pool size and maximum pool size as 2.
ThreadPoolExecutor executorService = new ThreadPoolExecutor(2, 2, 10, TimeUnit.MINUTES, queue)
queue is the LinkedBlockingQueue instance to store the tasks. 10 is the time to keep the additional threads(maximum pool size – core pool size) alive before its termination.TimeUnit is the unit of the above time. So here the time is 10 minutes . But we are not creating additional threads here.(Since core pool size and maximum pool size are 10).
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* User: Bijoy
* Date: 12/23/12
* Time: 7:45 PM
*/
public class ThreadPoolExecutorSample {
public ThreadPoolExecutorSample() {
}
public static void main(String[] args) {
Runnable firstTask = new Runnable() {
int number = 0;
public void run() {
while (number < 50) {
System.out.println("Thread :" + Thread.currentThread().getName() + " Number = " + number);
number = number + 10;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Runnable secondTask = new Runnable() {
int number = 50;
public void run() {
while (number < 100) {
System.out.println("Thread :" + Thread.currentThread().getName() + " Number = " + number);
number = number + 10;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Runnable thirdTask = new Runnable() {
int number = 100;
public void run() {
while (number < 150) {
System.out.println("Thread :" + Thread.currentThread().getName() + " Number = " + number);
number = number + 10;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Runnable fourthTask = new Runnable() {
int number = 150;
public void run() {
while (number < 200) {
System.out.println("Thread :" + Thread.currentThread().getName() + " Number = " + number);
number = number + 10;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
LinkedBlockingQueue
ThreadPoolExecutor executorService = new ThreadPoolExecutor(2, 2, 10, TimeUnit.MINUTES, queue);
executorService.execute(firstTask);
executorService.execute(secondTask);
executorService.execute(thirdTask);
executorService.execute(fourthTask);
}
}
Now let us see the output. There are only two threads to execute four tasks .So first two tasks will be taken first . Then after completion each thread will take the next task available in the queue. This can be well understood by analyzing the output.The thread status can be well identified by using any profiler. If we are using newer version of JDK ,then the bin directory contains JVisulaVM.exe . Open it and profile our Java process . Then we can see the status of each thread . After the four taks are over , the two threads are staying idle. It can be well understood by watching the profiler.
Output
Thread :pool-1-thread-1 Number = 0
Thread :pool-1-thread-2 Number = 50
Thread :pool-1-thread-2 Number = 60
Thread :pool-1-thread-1 Number = 10
Thread :pool-1-thread-2 Number = 70
Thread :pool-1-thread-1 Number = 20
Thread :pool-1-thread-2 Number = 80
Thread :pool-1-thread-1 Number = 30
Thread :pool-1-thread-2 Number = 90
Thread :pool-1-thread-1 Number = 40
Thread :pool-1-thread-1 Number = 100
Thread :pool-1-thread-2 Number = 150
Thread :pool-1-thread-1 Number = 110
Thread :pool-1-thread-2 Number = 160
Thread :pool-1-thread-2 Number = 170
Thread :pool-1-thread-1 Number = 120
Thread :pool-1-thread-2 Number = 180
Thread :pool-1-thread-1 Number = 130
Thread :pool-1-thread-2 Number = 190
Thread :pool-1-thread-1 Number = 140
See Related Discussions
The join() method in Threading
The yield() method in Threading