概念:
容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源。
线程池的好处:
1、降低资源消耗
2、提高响应速度
3、线程好管理
1. 降低资源消耗。减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。
2. 提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。
3. 提高线程的可管理性。可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。
使用步骤:
1. 创建线程池对象。
2. 创建Runnable接口子类对象。(task)
3. 提交Runnable接口子类对象。(take task)
4. 关闭线程池(一般不做)。
线程池的参数:
ThreadPoolExecutor的入参6个:核心线程数、最大线程数、线程空闲时间、时间单位、任务队列、拒绝策略
- 核心线程数(corePoolSize)是 ThreadPoolExecutor 在没有任务处理时保持活动的线程数量。即使这些线程处于空闲状态,它们也不会被回收。核心线程数始终保持在线程池中的线程数量。
- 最大线程数(maximumPoolSize)是 ThreadPoolExecutor 允许创建的最大线程数量。当有新任务提交到线程池中,而核心线程数已满时,线程池可以根据需要创建更多的线程,但总线程数不会超过最大线程数。如果达到了最大线程数并且工作队列也已满,那么新任务可能会被拒绝或以其他方式处理(根据线程池的拒绝策略)。
- 线程空闲时间:非核心线程被回收的时间限制。
- 任务队列:通过 new ArrayBlockingQueue<>(10) 创建一个容量为10的有界阻塞队列作为任务队列,有界阻塞队列可以控制任务的排队数量,当任务数量超过队列容量时,新的任务将会等待队列中的任务被处理完毕后再执行。
- 拒绝策略:有界队列并且队列已满时仍然继续添加新任务,可能会触发拒绝策略。拒绝策略指定了当线程池无法接受新的任务时应该采取的行动。在示例中,使用了默认的拒绝策略 AbortPolicy(中文名称:中止策略),即当线程池无法接受新的任务时,会抛出 RejectedExecutionException 异常。
任务队列和拒绝策略的选择根据具体场景和需求来确定。有界队列可以控制任务排队数量,避免资源耗尽,而拒绝策略可以决定当任务无法被接受时应该采取的行动。
使用示例:
import java.util.concurrent.*;
public class ThreadPoolExample {
public static void main(String[] args) {
// 创建线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, // 核心线程数
5, // 最大线程数
10, // 线程空闲时间
TimeUnit.SECONDS, // 时间单位
new ArrayBlockingQueue<>(10), // 任务队列
new ThreadPoolExecutor.AbortPolicy()); // 拒绝策略
// 提交任务给线程池
for (int i = 0; i < 10; i++) {
executor.execute(new Task(i));
}
// 关闭线程池
executor.shutdown();
}
static class Task implements Runnable {
private int taskId;
public Task(int taskId) {
this.taskId = taskId;
}
@Override
public void run() {
System.out.println("Task " + taskId + " is running.");
}
}
}
在这个示例中,创建了一个 `ThreadPoolExecutor` 对象 `executor`,设置了核心线程数为2,最大线程数为5,线程空闲时间为10秒,使用了一个容量为10的有界阻塞队列作为任务队列,并使用了默认的拒绝策略(`AbortPolicy`)。
然后,通过 `execute()` 方法向线程池提交了10个任务(`Task` 类实现了 `Runnable` 接口),每个任务简单地打印一条消息。最后,调用 `shutdown()` 方法关闭线程池。
当运行这个示例时,可以看到线程池会按顺序执行任务,并且能够自动管理核心线程、最大线程和任务队列等资源。