魔战英雄编年史作弊菜单
131.46MB · 2025-11-12
核心思想: 线程池是一种基于“池化”思想来管理线程的工具。它预先创建好一定数量的线程,放入一个“池子”中,当有任务需要执行时,就从池子中取出一个空闲线程来执行任务,任务执行完毕后,线程并不被销毁,而是返回池中等待执行下一个任务。
为什么需要线程池?
在深入原理之前,我们先想想如果不使用线程池,我们如何处理多任务:
// 原始方式:为每个任务创建一个新线程
for (int i = 0; i < 100; i++) {
new Thread(() -> {
// 执行任务
System.out.println("执行任务:" + Thread.currentThread().getName());
}).start();
}
这种方式存在几个严重问题:
线程池的优势:
要理解线程池的工作原理,我们需要深入到它的内部组件和执行流程。其核心模型可以用下图清晰地展示:
下面我们来详细拆解图中的每一步。
corePoolSize) :线程池中常驻的“核心部队”。即使它们处于空闲状态,也不会被销毁(除非设置了allowCoreThreadTimeOut为true)。workQueue) :一个阻塞队列,用于存放待执行的任务。当核心线程都在忙时,新来的任务会被放在这个队列里排队等候。maximumPoolSize) :线程池允许创建的最大线程数量。这是线程池的“扩编上限”。keepAliveTime决定)会被销毁。RejectedExecutionHandler) :当任务队列已满,并且线程数已达到最大值时,线程池会采取一种策略来处理新提交的任务。提交任务
当一个新任务被提交到线程池时,线程池的处理决策流程开始。
判断核心线程
corePoolSize(核心线程数),那么无论是否有空闲线程,线程池都会立即创建一个新的核心线程来执行这个任务。尝试入队
workQueue) 进行排队。判断最大线程
maximumPoolSize(最大线程数),线程池会创建一个新的非核心线程来立即执行这个任务(注意,它执行的是刚提交的这个新任务,而不是队列里的旧任务)。maximumPoolSize,则进入下一步。执行拒绝策略
RejectedExecutionHandler来处理这个任务。当线程池中的线程数量超过了corePoolSize,并且这些“多余”的非核心线程空闲时间超过了keepAliveTime,它们就会被终止,直到线程数量恢复到corePoolSize的大小。
ThreadPoolExecutor)在Java中,线程池的核心类是 java.util.concurrent.ThreadPoolExecutor。我们通常通过Executors工厂类来创建配置好的线程池,但更推荐直接使用ThreadPoolExecutor的构造函数来精细控制参数。
public ThreadPoolExecutor(
int corePoolSize, // 核心线程数
int maximumPoolSize, // 最大线程数
long keepAliveTime, // 非核心线程空闲存活时间
TimeUnit unit, // 存活时间单位
BlockingQueue<Runnable> workQueue, // 任务队列
ThreadFactory threadFactory, // 线程工厂(用于创建线程)
RejectedExecutionHandler handler // 拒绝策略
)
workQueue)SynchronousQueue:一个不存储元素的队列。每个插入操作必须等待另一个线程的移除操作。这样,提交的任务不会被排队,而是直接创建新线程或执行拒绝策略。Executors.newCachedThreadPool()使用它。LinkedBlockingQueue:一个基于链表的无界队列(除非构造时指定容量)。如果使用无界队列,那么maximumPoolSize参数就失效了,因为队列永远不会满,所以只会创建corePoolSize个线程。ArrayBlockingQueue:一个基于数组的有界队列。可以有效地防止资源耗尽。ThreadPoolExecutor.AbortPolicy(默认):直接抛出RejectedExecutionException异常。ThreadPoolExecutor.CallerRunsPolicy:由调用者所在线程(比如主线程)来执行该任务。这提供了一种简单的反馈控制机制,可以降低新任务的提交速度。ThreadPoolExecutor.DiscardPolicy:默默丢弃无法处理的任务,不抛异常。ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列中最旧的一个任务,然后尝试重新提交当前任务。Executors 工具类创建的常见线程池newFixedThreadPool (固定大小线程池)
corePoolSize = maximumPoolSize = nworkQueue = LinkedBlockingQueue(无界队列)newCachedThreadPool (可缓存线程池)
corePoolSize = 0maximumPoolSize = Integer.MAX_VALUE(几乎是无限的)keepAliveTime = 60秒workQueue = SynchronousQueuenewSingleThreadExecutor (单线程线程池)
corePoolSize = maximumPoolSize = 1workQueue = LinkedBlockingQueue(无界队列)newScheduledThreadPool (定时任务线程池)
理解参数:根据任务的特性(CPU密集型、IO密集型)合理设置corePoolSize、maximumPoolSize和workQueue。
推荐手动创建:避免使用Executors的便捷方法,而是直接使用ThreadPoolExecutor构造函数,这样可以更明确线程池的运行规则,规避资源耗尽的风险。
给线程池命名:通过自定义ThreadFactory,为线程设置有意义的名字,便于出错时回溯。
合理选择拒绝策略:根据业务重要性选择合适的拒绝策略。
总结一下:线程池是一个“生产者-消费者”模型的优雅实现。生产者提交任务(Runnable对象),消费者(池中的线程)从任务队列中获取并执行任务。通过预先创建和复用线程,以及对线程数量的管理,它极大地提升了多线程程序的性能、稳定性和可管理性。理解其核心工作原理是编写高效、健壮并发程序的关键。
如果小假的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!
131.46MB · 2025-11-12
74.32MB · 2025-11-12
10.47MB · 2025-11-12