Java线程池的核心实现类是ThreadPoolExecutor。其继承关系为ThreadPoolExecutor -> AbstractExecutorService -> ExecutorService -> Executor。
运行机制如下图所示:
ThreadPoolExecutor运行机制线程池的运行主要分为2个部分,任务管理和线程管理。任务管理是生产者,当任务提交后,线程池会判断线程后续的流转,1⃣️新建线程,执行任务 2⃣️将任务放入缓冲队列 3⃣️ 执行拒绝策略。线程管理是消费者,它们被维护在线程池中,根据任务的请求进行线程的分配,执行完任务后会循环请求队列进行下次任务的执行,超过一定的时间没有获取到任务就会被回收。
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
ctl利用低29位表示线程池中线程数,通过高3位表示线程池的运行状态,线程池中经常出现要同时判断线程池运行状态和线程数量的情况,用一个变量去存储两个值,可避免在做相关决策时,出现不一致的情况,不必为了维护两者的一致,而占用锁资源。
ThreadPoolExecutor的运行状态有5种,分别为:
线程池状态描述 线程池生命周期任务的执行过程,
execute –> addWorker –>runWorker (getTask)
execute()方法:ThreadPoolExecutor.execute(task)实现了Executor.execute(task)
任务申请:任务的执行有两种可能:一种是任务直接由新创建的线程执行。另一种是线程从任务队列中获取任务然后执行,执行完任务的空闲线程会再次去从队列中申请任务再去执行。第一种情况仅出现在线程初始创建的时候,第二种是线程获取任务绝大多数的情况。
addWorker()方法:ThreadPoolExecutor的private方法
增加线程:该方法不考虑线程池是在哪个阶段增加的该线程,这个分配线程的策略是在上个步骤完成的,该步骤仅仅完成增加线程,并使它运行,最后返回是否成功这个结果。addWorker方法有两个参数:firstTask、core。firstTask参数用于指定新增的线程执行的第一个任务,该参数可以为空;core参数为true表示在新增线程时会判断当前活动线程数是否少于corePoolSize,false表示新增线程前需要判断当前活动线程数是否少于maximumPoolSize。(线程池创建新线程执行任务时,需要 获取全局锁ReentrantLock mainLock),worker创建成功后会将worker加入到hashset.
runworker方法: Worker类中的方法
1.while循环不断地通过getTask()方法获取任务。 2.getTask()方法从阻塞队列中取任务。 3.如果线程池正在停止,那么要保证当前线程是中断状态,否则要保证当前线程不是中断状态。 4.执行任务。 5.如果getTask结果为null则跳出循环,执行processWorkerExit()方法,销毁线程。
getTask方法:从阻塞队列中获取等待的任务
注意这里一段代码是keepAliveTime起作用的关键
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
网友评论