线程池是一种用于多线程管理的机制,它可以有效管理将要执行的任务,减轻了创建和销毁线程的负担。通过复用现有线程,避免了大量线程创建和销毁过程中的开销,从而提高了应用程序的性能和可伸缩性。
线程池的优势主要体现在以下几个方面:
在 Java 中,可以使用 java.util.concurrent
包中的线程池来实现线程管理。常用的线程池类型有以下四种:
FixedThreadPool
:该线程池类型的核心线程数是固定的,同时也允许在池中创建的线程数量保持不变。一般情况下它使用无界队列,即可以放入无限多的任务。CachedThreadPool
:该线程池类型的核心线程数是 0,为非固定值。当池中线程数量不够用时,会创建新的线程,而池中线程数量缩减时,会回收后面的线程。此种类型线程池在取得一个工作线程时总是先尝试复用之前的线程。SingleThreadExecutor
:该线程池类型只有一个线程,每提交一个任务就会产生一个任务。ScheduledThreadPool
:该线程池支持延迟执行和定时执行的任务。使用线程池的主要过程是:
它的基本代码如下所示:
// 创建一个大小固定为 5 的线程池
ExecutorService executorService = Executors.newFixedThreadPool(5);
// 创建任务并提交到线程池中执行
executorService.execute(new Runnable() {
@Override
public void run() {
// 业务处理逻辑
}
});
// 等待任务执行完成,关闭线程池
executorService.shutdown();
FixedThreadPool
下面是一个使用 FixedThreadPool
的示例代码:
// 创建一个核心线程数为 5 的固定线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
// 提交至少 10 个任务到线程池中
for (int i = 1; i <= 10; i++) {
fixedThreadPool.execute(new Task(i));
}
// 关闭线程池
fixedThreadPool.shutdown();
class Task implements Runnable {
private int taskId;
public Task(int taskId) {
this.taskId = taskId;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 执行任务 " + taskId);
}
}
在该示例中,线程池的核心线程数是 5,然后将 10 个任务添加到线程池中进行执行。程序的执行结果为:
pool-1-thread-2 执行任务 2
pool-1-thread-1 执行任务 1
pool-1-thread-3 执行任务 3
pool-1-thread-4 执行任务 4
pool-1-thread-5 执行任务 5
pool-1-thread-5 执行任务 6
pool-1-thread-2 执行任务 7
pool-1-thread-4 执行任务 8
pool-1-thread-1 执行任务 9
pool-1-thread-3 执行任务 10
ScheduledThreadPool
下面是一个使用 ScheduledThreadPool
的示例代码:
// 创建一个大小固定为 5 的线程池
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
// 延迟 1 秒后执行任务
scheduledExecutorService.schedule(new Task(), 1L, TimeUnit.SECONDS);
// 延迟 3 秒后执行任务
scheduledExecutorService.schedule(new Task(), 3L, TimeUnit.SECONDS);
// 每 1 秒执行一次任务
scheduledExecutorService.scheduleAtFixedRate(new Task(), 0L, 1L, TimeUnit.SECONDS);
// 每 3 秒执行一次任务
scheduledExecutorService.scheduleWithFixedDelay(new Task(), 0L, 3L, TimeUnit.SECONDS);
// 关闭线程池
scheduledExecutorService.shutdown();
class Task implements Runnable {
@Override
public void run() {
System.out.println("当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
}
在该示例中,线程池的核心线程数是 5,然后分别在 1s 和 3s 后执行任务,每隔 1s 和 3s 执行一次任务。程序的执行结果为:
当前时间:2021-11-06 16:06:16
当前时间:2021-11-06 16:06:17
当前时间:2021-11-06 16:06:17
当前时间:2021-11-06 16:06:18
当前时间:2021-11-06 16:06:18
当前时间:2021-11-06 16:06:19
当前时间:2021-11-06 16:06:19
当前时间:2021-11-06 16:06:20
当前时间:2021-11-06 16:06:20
当前时间:2021-11-06 16:06:21