Problems with Direct Thread Creation and the Benefits of Using Thread Pools in Java
The article explains why creating and destroying threads directly is inefficient and risky for high‑traffic services, then introduces thread pools as a solution, detailing four common pool types with code examples, their advantages, limitations, and overall impact on system performance.
Creating a new Thread for each task incurs high overhead because frequent object creation and destruction consume CPU and memory, and when many users are present the uncontrolled number of threads can exhaust resources and cause service crashes.
Using a thread pool solves these problems by reusing a fixed set of threads, reducing creation costs, controlling concurrency, and improving server resource utilization.
Four Common ThreadPool Types
1. newCachedThreadPool
This pool creates new threads as needed and reclaims idle ones, allowing dynamic scaling while avoiding excess thread accumulation.
public static void method() throws Exception {
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
final int index = i;
Thread.sleep(1000);
executor.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " " + index);
}
});
}
}The execution shows a single thread handling all tasks sequentially, demonstrating thread reuse.
2. newFixedThreadPool
This pool fixes the number of threads, similar to limiting the capacity of a bathhouse; excess tasks wait in a queue, preventing resource over‑commitment.
public static void method_01() throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(1);
for (int i = 0; i < 10; i++) {
Thread.sleep(1000);
final int index = i;
executor.execute(() -> {
try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(Thread.currentThread().getName() + " " + index);
});
}
executor.shutdown();
}Running with a single thread serializes the tasks; increasing the pool size to three shows concurrent execution while still limiting the maximum number of active threads.
3. newScheduledThreadPool
This pool supports delayed and periodic task execution. Two scheduling methods are demonstrated:
scheduleAtFixedRate – executes at a fixed interval regardless of task duration.
scheduleWithFixedDelay – starts the next execution after the previous task finishes plus a fixed delay.
public static void method_02() {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
executor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
long start = new Date().getTime();
System.out.println("scheduleAtFixedRate start:" + DateFormat.getTimeInstance().format(new Date()));
try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); }
long end = new Date().getTime();
System.out.println("scheduleAtFixedRate cost=" + (end - start) / 1000 + "s");
System.out.println("scheduleAtFixedRate end:" + DateFormat.getTimeInstance().format(new Date()));
System.out.println("====================");
}
}, 1, 5, TimeUnit.SECONDS);
}Tests show that when the interval exceeds task duration, the schedule is unaffected; when the interval is shorter, tasks run back‑to‑back, distorting the intended spacing.
4. newSingleThreadExecutor
A single‑threaded pool guarantees that all submitted tasks run sequentially on the same thread.
public static void method_04() {
ExecutorService executor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
final int index = i;
executor.execute(() -> {
try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(Thread.currentThread().getName() + " " + index);
});
}
executor.shutdown();
}Purpose of Thread Pools
Thread pools improve system performance and resource utilization by avoiding the overhead of constantly creating and destroying threads, similar to how database connection pools reduce the cost of frequent connection establishment.
Conclusion: Selecting the appropriate thread‑pool type allows developers to balance concurrency, resource usage, and task scheduling requirements, leading to more stable and efficient Java applications.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
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.
