Thread programming is a technique that allows a program do divide itself into multiple, concurently executing tasks called threads, which can improve performance and responsiveness by utilising multiple CPU cores or by allowing a single core to switch between tasks rapidly. When tackling with threads, however, we might carelessly manage the creation of threads leading to bottleneck where using thread pools could be strongly recommended. Have you heard about thread pool in Java? In this post, we will show you a simple usage of thread pool that you can find the effectiveness of concurent programming.
Table of Contents
Introduction
Java thread pool is designed to manage the pool of worker threads. It has a blocking queue that keeps tasks waiting to get executed. Why? The creation of threads for every task is expensive and unmanageable. Therefore, thread pools can be used to control how many threads should be created and recyle the existing ones if they are idle. Also, creating threads in a specific pool is manageable.
Demonstration
We need to create two classes: main class for the entry point and a runnable class implements Runnable, where it is called worker.
The WorkerThread class looks like below.
package com.itersdesktop.javatechs.concurrent.threadpools;
public class WorkerThread implements Runnable {
private String command;
public WorkerThread(String s){
this.command = s;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" Start. Command = "+command);
processCommand();
System.out.println(Thread.currentThread().getName()+" End.");
}
private void processCommand() {
try {
System.out.println(Thread.currentThread().getName()+" Process Command = "+command);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public String toString(){
return this.command;
}
}
The SimpleThreadPool main class is implemented as below.
package com.itersdesktop.javatechs.concurrent.threadpools;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SimpleThreadPool {
public static void main(String[] args) {
runWorkersSequentially();
runWorkersConcurrently();
}
private static void runWorkersConcurrently() {
long time = System.nanoTime();
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
Runnable worker = new WorkerThread("" + i);
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {
// wait for finishing
}
System.out.println("Finished all threads");
time = (System.nanoTime() - time) / 1_000_000;
System.out.println("It takes " + time + " milliseconds!");
}
private static void runWorkersSequentially() {
long time = System.nanoTime();
for (int i = 0; i < 10; i++) {
Runnable worker = new WorkerThread("" + i);
worker.run();
}
time = (System.nanoTime() - time) / 1_000_000;
System.out.println("It takes " + time + " milliseconds!");
}
}
The main class implements two approaches: sequentally and concurrently. Running the main class, the result shows interesting. With my MacBook Pro 16-inch, Apple M4 Pro, 24 GB RAM, the running time is quite different.
| Header 1 | Sequentially | Concurrently |
|---|---|---|
| Run 1 | 10.030 | 2.010 |
| Run 2 | 10.051 | 2.010 |
| Run 3 | 10.034 | 2.010 |
Apparently, this toy program is just aimed to test thread pool. We can make it more complex to real use cases.
The source codes are published here.
References
[1] ThreadPoolExecutor – Java ThreadPool Example, https://www.digitalocean.com/community/tutorials/threadpoolexecutor-java-thread-pool-example-executorservice, accessed on July 16th, 2025
[2] Introduction to Thread Pools in Java, https://www.baeldung.com/thread-pool-java-and-guava, accessed on July 16th, 2025
