
在 Java 中有几种类型的线程池可以用于处理多线程任务,以下是常见的5种Java线程池@mikechen
FixedThreadPool(固定线程池)
固定线程池会创建一个固定数量的线程,并在池中保持这些线程的数量不变。
如下所示:
// 创建一个固定线程数量为 3 的线程池
ExecutorService executor = Executors.newFixedThreadPool(3);
// 提交任务
for (int i = 0; i < 10; i++) {
final int taskId = i;
executor.execute(() -> {
System.out.println("Task " + taskId + " is being executed by thread " + Thread.currentThread().getName());
});
}
// 关闭线程池
executor.shutdown();
适用场景:
- 当有固定数量的并发任务需要处理时。
- 希望限制线程数量,防止过多线程导致资源耗尽。
注意事项:
- 由于线程数量是固定的,如果同时有大量任务提交,可能会导致工作队列积压,因此需要根据实际情况来选择线程池的大小。
- 当任务量较小时,固定线程池可能会浪费一些线程资源,如果在任务量不确定的情况下,可以考虑使用缓存线程池。
CachedThreadPool(缓存线程池)
缓存线程池会根据需要动态地创建线程,并在一段时间内重用空闲线程,通常是60秒。
如下所示:
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int taskId = i;
executor.execute(() -> {
System.out.println("Task " + taskId + " is being executed by thread " + Thread.currentThread().getName());
});
}
executor.shutdown();
适用场景:
缓存线程池适用于短期任务数量不确定的场景,特别是在处理大量的短期任务时,它可以根据任务的数量动态地分配和回收线程,以提供最佳的并发性能。
注意事项:
- 虽然缓存线程池在短期任务处理上非常高效,但在处理长期任务时,可能会导致过多的线程占用系统资源。
- 当不再需要线程池时,务必调用
shutdown()方法来释放线程资源,避免资源泄漏。
SingleThreadExecutor(单线程池)
单线程池只有一个工作线程,用于按照顺序执行提交的任务,所有任务按照它们的提交顺序在同一个线程中执行。
如下所示 :
ExecutorService executor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int taskId = i;
executor.execute(() -> {
System.out.println("Task " + taskId + " is being executed by thread " + Thread.currentThread().getName());
});
}
executor.shutdown();
适用场景:
- 单线程池适用于需要按顺序执行任务的场景,例如需要保证任务的顺序执行,避免并发带来的问题。
- 也适用于需要在单个线程中执行任务,以避免并发的复杂性。
注意事项:
- 单线程池适用于保证任务顺序执行的场景,但不适合需要高并发处理的情况。
- 虽然只有一个线程在执行任务,但如果有异常抛出,线程池会创建一个新线程来继续执行后续任务。
ScheduledThreadPool(调度线程池)
调度线程池(ScheduledThreadPool)是 Java 中一种特殊的线程池类型,用于执行定时任务或周期性任务。
如下所示:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
Runnable task = () -> {
System.out.println("Scheduled task executed at " + System.currentTimeMillis());
};
// 延迟2秒执行任务
executor.schedule(task, 2, TimeUnit.SECONDS);
// 延迟1秒后每3秒执行一次
executor.scheduleAtFixedRate(task, 1, 3, TimeUnit.SECONDS);
// 关闭线程池
executor.shutdown();
适用场景:
调度线程池适用于需要按计划执行任务的场景,例如:定时生成报表、定时数据清理、周期性检查等。
注意事项:
- 调度线程池适用于需要按计划执行任务的场景,但需要考虑任务执行时间和调度间隔,避免任务堆积或执行过长导致的问题。
- 当不再需要线程池时,务必调用
shutdown()方法来释放线程资源,避免资源泄漏。
WorkStealingPool(工作窃取线程池)
工作窃取线程池是 Java 7 引入的一种线程池,它基于 “工作窃取” 的概念。
每个线程维护自己的任务队列,当一个线程的任务队列为空时,它可以从其他线程的任务队列中窃取任务来执行。
如下所示:
ForkJoinPool executor = new ForkJoinPool(); int[] array = new int[1000000]; RecursiveTask<Integer> task = new CustomTask(array, 0, array.length); executor.invoke(task); executor.shutdown();
这种线程池适用于一些需要大量计算的并行任务。
以上就是5种Java线程池的用法和适用场景,你可以选择适合你应用程序的线程池类型,以优化并发处理和资源利用。
mikechen睿哥
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。