Java ThreadPool Creation Methods and Usage Examples
This article explains the seven ways to create Java thread pools, categorizes them by ThreadPoolExecutor and Executors, and provides detailed code examples for fixed-size, cached, scheduled, single‑thread, work‑stealing pools, as well as custom thread factories and task result handling.
The creation of thread pools in Java has seven methods, which can be divided into two main categories: pools created via ThreadPoolExecutor and pools created via the Executors utility class.
The seven specific creation methods are:
Executors.newFixedThreadPool : creates a pool with a fixed number of threads; excess tasks wait in a queue.
Executors.newCachedThreadPool : creates a pool that reuses idle threads and creates new ones when needed.
Executors.newSingleThreadExecutor : creates a single‑threaded pool that guarantees FIFO execution.
Executors.newScheduledThreadPool : creates a pool that can execute delayed or periodic tasks.
Executors.newSingleThreadScheduledExecutor : a single‑threaded scheduled pool.
Executors.newWorkStealingPool (added in JDK 1.8): creates a work‑stealing pool with nondeterministic task order.
ThreadPoolExecutor : the most configurable way, exposing seven parameters for fine‑tuning.
1. Fixed‑size thread pool
public class ThreadPoolDemo3 {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(2);
// Task 1
threadPool.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
// Task 2
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
}
// Output:
// pool-1-thread-1
// pool-1-thread-2Using submit returns a Future that can hold a result, while execute only runs a task without a return value.
2. Custom thread factory (name & priority)
public class ThreadPoolDemo5 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ThreadFactory threadFactory = new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("MyThread" + r.hashCode());
thread.setPriority(Thread.MAX_PRIORITY);
return thread;
}
};
ExecutorService threadPool = Executors.newFixedThreadPool(2, threadFactory);
Future
result = threadPool.submit(new Callable
() {
@Override
public Integer call() throws Exception {
int num = new Random().nextInt(10);
System.out.println(Thread.currentThread().getPriority() + ", random: " + num);
return num;
}
});
System.out.println("Result: " + result.get());
}
}The custom factory allows setting thread naming rules, priority, group, and daemon status.
3. Cached thread pool
public class ThreadPoolDemo6 {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
int finalI = i;
service.submit(() -> {
System.out.println("i : " + finalI + " | thread: " + Thread.currentThread().getName());
});
}
}
}This pool creates threads as needed and reuses idle ones after a timeout; it is suitable for short‑lived, bursty workloads but may consume many resources.
4. Scheduled tasks
a. One‑time delayed execution
public class ThreadPoolDemo7 {
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
System.out.println("Add time: " + LocalDateTime.now());
service.schedule(new Runnable() {
@Override
public void run() {
System.out.println("Run time: " + LocalDateTime.now());
}
}, 3, TimeUnit.SECONDS);
}
}b. Fixed‑rate execution
public class ThreadPoolDemo8 {
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
System.out.println("Add time: " + LocalDateTime.now());
service.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("Run task: " + LocalDateTime.now());
}
}, 2, 4, TimeUnit.SECONDS);
}
}c. Fixed‑delay execution
public class ThreadPoolDemo10 {
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
System.out.println("Add time: " + LocalDateTime.now());
service.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
System.out.println("Run task: " + LocalDateTime.now());
try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
}
}, 2, 4, TimeUnit.SECONDS);
}
}scheduleAtFixedRate uses the start time of the previous execution as the reference, while scheduleWithFixedDelay uses the end time, causing different spacing when tasks take longer.
5. Single‑thread scheduled executor
public class ThreadPoolDemo11 {
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
System.out.println("Add time: " + LocalDateTime.now());
service.schedule(() -> System.out.println("Run time: " + LocalDateTime.now()), 2, TimeUnit.SECONDS);
}
}6. Single‑thread pool
public class ThreadPoolDemo12 {
public static void main(String[] args) {
ExecutorService service = Executors.newSingleThreadScheduledExecutor();
for (int i = 0; i < 10; i++) {
service.submit(() -> System.out.println("Thread name: " + Thread.currentThread().getName()));
}
}
}A single‑thread pool reuses one thread, provides a task queue and rejection policy when the queue is full.
7. Work‑stealing pool (CPU‑based)
public class ThreadPoolDemo13 {
public static void main(String[] args) {
ExecutorService service = Executors.newWorkStealingPool();
for (int i = 0; i < 10; i++) {
service.submit(() -> System.out.println("Thread name " + Thread.currentThread().getName()));
}
}
}This pool creates a number of worker threads based on the number of available processors and uses a work‑stealing algorithm for load balancing.
8. Direct use of ThreadPoolExecutor
For full control over core pool size, maximum pool size, keep‑alive time, work queue, thread factory, and rejection handler, instantiate ThreadPoolExecutor directly. Detailed parameter explanations can be found in the referenced blog post.
Overall, choosing the appropriate thread‑pool creation method depends on the task characteristics, required concurrency level, and resource constraints.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.