ThreadPoolExecutor可以创建哪是哪三种线程池呢?
ThreadPoolExecutor
是一个非常灵活的类,可以根据不同的参数配置来创建不同类型的线程池。尽管它本身没有硬性规定必须创建某三种线程池,但常见的线程池类型通常有以下三种:固定大小线程池、缓存线程池和单线程池。这些常见的线程池类型可以通过 Executors
工具类来创建,并且底层实现都使用了 ThreadPoolExecutor
。
具体而言,它们可以概括为以下三种:
1. 固定大小线程池(Fixed Thread Pool)
固定大小的线程池,具有固定数量的核心线程,并且不会回收这些线程。此类型的线程池适用于负载较稳定的场景。
创建方式:
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(int nThreads);
等价的 ThreadPoolExecutor
配置:
int nThreads = 4;
ExecutorService fixedThreadPool = new ThreadPoolExecutor(
nThreads,
nThreads,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()
);
2. 缓存线程池(Cached Thread Pool)
缓存线程池可根据需求创建新线程,如果旧线程在指定时间内没有被使用,则会回收这些线程。适用于大量短生命周期的异步任务的场景。
创建方式:
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
等价的 ThreadPoolExecutor
配置:
ExecutorService cachedThreadPool = new ThreadPoolExecutor(
0,
Integer.MAX_VALUE,
60L,
TimeUnit.SECONDS,
new SynchronousQueue<Runnable>()
);
3. 单线程池(Single Thread Executor)
单线程池内部只有一个线程来执行任务,所有任务会被顺序地执行。适用于需要顺序执行的场景,以及需要保证线程安全的单例任务执行环境。
创建方式:
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
等价的 ThreadPoolExecutor
配置:
ExecutorService singleThreadExecutor = new ThreadPoolExecutor(
1,
1,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()
);
4. 调度线程池(Scheduled Thread Pool)
除了上面的三种常见线程池类型之外,ThreadPoolExecutor
还用于实现调度线程池(ScheduledThreadPool
),这类线程池可以用于调度定时任务。
创建方式:
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(int corePoolSize);
底层实现:
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(
corePoolSize,
Integer.MAX_VALUE,
0,
NANOSECONDS,
new DelayedWorkQueue()
);
}
示例代码
举例说明如何使用 ThreadPoolExecutor
配置不同的线程池:
import java.util.concurrent.*;
public class DifferentThreadPoolsExample {
public static void main(String[] args) {
// 固定大小线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);
// 提交任务
for (int i = 0; i < 10; i++) {
final int taskNumber = i;
fixedThreadPool.submit(() -> {
try {
System.out.println("Fixed Task " + taskNumber + " is running by " + Thread.currentThread().getName());
Thread.sleep(2000);
System.out.println("Fixed Task " + taskNumber + " is completed by " + Thread.currentThread().getName());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
// 缓存线程池
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int taskNumber = i;
cachedThreadPool.submit(() -> {
try {
System.out.println("Cached Task " + taskNumber + " is running by " + Thread.currentThread().getName());
Thread.sleep(2000);
System.out.println("Cached Task " + taskNumber + " is completed by " + Thread.currentThread().getName());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
// 单线程池
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int taskNumber = i;
singleThreadExecutor.submit(() -> {
try {
System.out.println("Single Task " + taskNumber + " is running by " + Thread.currentThread().getName());
Thread.sleep(2000);
System.out.println("Single Task " + taskNumber + " is completed by " + Thread.currentThread().getName());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
// 通过 shutdown 关闭线程池
fixedThreadPool.shutdown();
cachedThreadPool.shutdown();
singleThreadExecutor.shutdown();
// 延时调度线程池(额外的)
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
scheduledExecutorService.schedule(() -> {
System.out.println("Scheduled Task is running by " + Thread.currentThread().getName());
}, 5, TimeUnit.SECONDS);
scheduledExecutorService.shutdown();
}
}
总结
虽然上面常见的三种线程池类型是最常用的,但 ThreadPoolExecutor
的灵活性使您可以创建几乎任何类型的线程池以适应特定的应用需求。理解这些基本类型的工作原理和适用场景将有助于在实际项目中更有效地使用线程池。