Java 标准库中提供了哪些内置的线程池实现?请列举并说明其特点。
参考回答
Java 标准库中的 Executors 工具类提供了以下常用的内置线程池实现:
newFixedThreadPool(int nThreads):
创建一个固定大小的线程池。
线程池中的线程数始终保持为 nThreads。
适用于需要限制线程数量的场景。
newCachedThreadPool():
创建一个缓存线程池。
如果线程空闲且超过 60 秒未被使用,会被回收;如果有新任务,会复用已有线程或创建新线程。
适用于短时间内有大量任务的场景。
newSingleThreadExecutor():
创建一个单线程的线程池。
确保任务按提交顺序串行执行。
适用于需要顺序执行任务的场景。
newScheduledThreadPool(int corePoolSize):
创建一个支持定时任务和周期性任务的线程池。
可以延迟执行任务或按固定频率执行任务。
适用于需要定时调度的场景。
详细讲解与拓展
1. FixedThreadPool
特点:
线程池中的线程数是固定的。
如果任务数量超过线程数,超出的任务会进入等待队列。
示例代码:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class FixedThreadPoolExample {
public static void main(String[] args) {
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 1; i <= 5; i++) {
int taskId = i;
fixedThreadPool.execute(() -> {
System.out.println(“Task ” + taskId + ” executed by ” + Thread.currentThread().getName());
});
}
fixedThreadPool.shutdown();
}
}
输出:
Task 1 executed by pool-1-thread-1
Task 2 executed by pool-1-thread-2
Task 3 executed by pool-1-thread-3
Task 4 executed by pool-1-thread-1
Task 5 executed by pool-1-thread-2
适用场景:
适合处理恒定数量的任务,例如固定数量的 IO 操作。
- CachedThreadPool
特点:
线程池大小不固定,空闲线程会被回收,新任务到来时可创建新线程。
在任务数量非常大的场景下容易占用大量资源,需要注意控制任务提交速率。
示例代码:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CachedThreadPoolExample {
public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 1; i <= 5; i++) {
int taskId = i;
cachedThreadPool.execute(() -> {
System.out.println(“Task ” + taskId + ” executed by ” + Thread.currentThread().getName());
});
}
cachedThreadPool.shutdown();
}
}
输出(线程可能动态创建):
Task 1 executed by pool-1-thread-1
Task 2 executed by pool-1-thread-2
Task 3 executed by pool-1-thread-3
Task 4 executed by pool-1-thread-4
Task 5 executed by pool-1-thread-5
适用场景:
适合执行大量短时间的小任务,例如请求处理。
- SingleThreadExecutor
特点:
只有一个线程,所有任务按提交顺序依次执行。
线程异常终止时,会创建一个新线程继续执行任务。
示例代码:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SingleThreadExecutorExample {
public static void main(String[] args) {
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 1; i <= 3; i++) {
int taskId = i;
singleThreadExecutor.execute(() -> {
System.out.println(“Task ” + taskId + ” executed by ” + Thread.currentThread().getName());
});
}
singleThreadExecutor.shutdown();
}
}
输出:
Task 1 executed by pool-1-thread-1
Task 2 executed by pool-1-thread-1
Task 3 executed by pool-1-thread-1
适用场景:
适合需要任务严格顺序执行的场景,例如日志写入。
- ScheduledThreadPool
特点:
支持定时执行任务或周期性执行任务。
提供方法:
schedule(Runnable, delay, TimeUnit):延迟执行任务。
scheduleAtFixedRate(Runnable, initialDelay, period, TimeUnit):按固定速率周期执行任务。
scheduleWithFixedDelay(Runnable, initialDelay, delay, TimeUnit):按固定延迟周期执行任务。
示例代码:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledThreadPoolExample {
public static void main(String[] args) {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(2);
// 延迟 2 秒执行任务
scheduledThreadPool.schedule(() -> {
System.out.println("Task executed after delay");
}, 2, TimeUnit.SECONDS);
// 每 3 秒执行一次任务
scheduledThreadPool.scheduleAtFixedRate(() -> {
System.out.println("Periodic task executed");
}, 1, 3, TimeUnit.SECONDS);
// 关闭线程池,延时10秒
scheduledThreadPool.schedule(() -> scheduledThreadPool.shutdown(), 10, TimeUnit.SECONDS);
}
}
输出示例:
Periodic task executed
Task executed after delay
Periodic task executed
Periodic task executed
…
适用场景:
定时任务,如定期清理缓存、监控系统状态等。
扩展:ThreadPoolExecutor
以上 Executors 创建的线程池实际上是 ThreadPoolExecutor 的封装,ThreadPoolExecutor 提供更灵活的配置:
核心线程数(corePoolSize):线程池中始终存活的线程数量。
最大线程数(maximumPoolSize):线程池中允许的最大线程数量。
任务队列:用于存储等待执行的任务。
拒绝策略:当线程池饱和时的任务处理策略(如抛异常、丢弃任务等)。
自定义线程池示例:
import java.util.concurrent.*;
public class CustomThreadPoolExample {
public static void main(String[] args) {
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
2, // 核心线程数
5, // 最大线程数
60, // 空闲线程存活时间
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(10) // 任务队列
);
for (int i = 1; i <= 15; i++) {
int taskId = i;
threadPool.execute(() -> {
System.out.println(“Task ” + taskId + ” executed by ” + Thread.currentThread().getName());
});
}
threadPool.shutdown();
}
}
总结
线程池类型 特点 适用场景
FixedThreadPool 固定线程数,任务超出线程数会进入队列 任务量稳定的场景,如处理固定数量的请求
CachedThreadPool 线程数不固定,空闲线程会被回收 大量短期任务的场景,如高并发请求处理
SingleThreadExecutor 单线程,任务按顺序执行 保证任务顺序执行的场景,如日志写入
ScheduledThreadPool 支持延迟和周期性任务 定时任务,如监控、缓存清理