Threading-ThreadPoolExecutor in java

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 queue = new 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

Threading Basics

Thread Safety in Java

Thread Communication in Java

Thread Priorities in Java

The join() method in Threading

The yield() method in Threading

The sleep() method in threading

Daemon Threads in Java

Thread pools in Java

Thread Dead lock in Java

Thread Live lock in Java