- 线程池是怎么实现的
线程池是一种基于池化技术的线程管理方式,通过预先创建一定数量的线程并保持在池中待命,从而在有任务来临时能够快速分配线程处理任务,而无需频繁创建和销毁线程,以此达到提升系统性能、减少资源消耗的目的。
Java中的线程池实现 -ThreadPoolExecutor
Java中最常用的线程池实现是java.util.concurrent.ThreadPoolExecutor类,它实现了ExecutorService接口。ThreadPoolExecutor的设计围绕着几个关键组成部分:
corePoolSize(核心线程数):
定义了线程池中的常驻核心线程数。即使这些线程当前是空闲的,它们也会一直存在,除非设置了allowCoreThreadTimeOut为true,此时核心线程在空闲时也会超时终止。
maximumPoolSize(最大线程数):
表示线程池能够容纳同时执行的最大线程数,包括核心线程和非核心线程。当活动线程数达到这个值后,新任务将会被阻塞或拒绝。
keepAliveTime(空闲线程存活时间):
当线程数超过核心线程数时,超出的空闲线程在等待新任务的最长时间。达到这个时间后,多余的空闲线程会被终止,直到线程数减少到核心线程数。
unit(存活时间单位):
用于指定keepAliveTime参数的时间单位,例如TimeUnit.SECONDS(秒)、TimeUnit.MILLISECONDS(毫秒)等。
workQueue(工作队列):
用于保存待处理的任务队列。当线程池中的线程数目达到最大值时,新提交的任务会存储在这个队列中等待执行。JDK提供了多种队列实现,如ArrayBlockingQueue(有界队列)、LinkedBlockingQueue(可选边界队列,默认情况下是无界的)、SynchronousQueue(直接交换,通常用于无缓冲的生产者-消费者场景)和PriorityBlockingQueue(带优先级的队列)。
threadFactory(线程工厂):
用于创建新线程的工厂,可以用来设置线程的优先级、线程组、名称等属性。如果不指定,默认使用Executors.defaultThreadFactory()。
handler(拒绝策略):
当线程池和任务队列都达到饱和时(即无法再接受新任务),用于处理额外任务的策略。有四种预定义的策略:
AbortPolicy:默认策略,抛出RejectedExecutionException异常。
CallerRunsPolicy:调用者运行任务的策略,即提交任务的线程自己执行该任务。
DiscardPolicy:静默丢弃无法处理的任务,不抛出异常。
DiscardOldestPolicy:丢弃队列中最旧的任务,并尝试重新提交当前任务。
实现原理简述
任务提交:当一个新任务通过execute()方法提交给线程池时,线程池首先会尝试直接将任务交给核心线程执行。
线程创建与任务调度:如果核心线程都在忙且任务队列未满,则新任务会被放入任务队列等待。如果任务队列已满,且当前线程数小于最大线程数,那么会创建新的线程来执行任务。
线程回收:当线程池中的线程数量超过核心线程数并且有线程空闲超过keepAliveTime时,这些空闲线程会被终止,直到线程数量降到核心线程数。
如果大家需要视频版本的讲解,欢迎关注我的B站: