美文网首页
ThreadPoolExecutor线程池

ThreadPoolExecutor线程池

作者: 我要赚钱出去玩 | 来源:发表于2020-07-03 11:22 被阅读0次

最近在学习Java基础,正在阅读《Java并发编程实战》,该书总结的规律性内容偏多,关于JDK底层实现介绍较少,为提升Java多线程基础,萌生了阅读concurrent包源码的想法,夯实基础,从阅读源码开始ヾ(◍°∇°◍)ノ゙

UML类图

类图

函数调用关系

关键函数调用关系

线程池中的基本概念

基础概念

定义

线程池是一种生产者-消费者的模型,底层基于阻塞队列+ReentrantLock+CAS+volitate+原子类实现线程安全。线程池中有两个基础概念:工作线程和任务。用户提交任务,线程池为任务分配工作线程(1:N),线程池中的工作线程属于内部类Worker的实例。其中firstTask代表工作线程将要执行的任务,thread表示执行任务的线程,thread由线程工场负责创建。

private final class Worker extends AbstractQueuedSynchronizer implements Runnable
    {
        final Thread thread;
        Runnable firstTask;
        volatile long completedTasks;
        Worker(Runnable firstTask) {
            setState(-1); // inhibit interrupts until runWorker
            this.firstTask = firstTask;
            this.thread = getThreadFactory().newThread(this);
        }
       public void run() {
            runWorker(this);
        }
}

线程池生命周期

线程池状态转换.png

基本属性

  • ctl 线程池的状态代码,ctl是原子类的Integer 32bit,包含了两种信息:其中最高的3bit代表线程池的状态runState,剩余的表示线程池中的有效可用线程数workerCount。
  • 利用CAS的方式更新线程池状态以及workerCount
  • 这里为什么要这样设计呢?
    [1] AutoInteger原子类保证了线程安全
    [2] 状态和数量用一个数值表示,利用位运算获得状态和数量,效率更高??
  • workerCount != 线程池存活线程数,具体指的是什么?不是很懂
  • workQueue 阻塞队列,保存用户提交的任务。

  • mainLock 线程池的ReentrantLock,在对工作线程进行操作之前需要获得这个锁,保证线程安全。

所有涉及到worker的操作都需要首先获取锁(这是由于worker为HashSet属于线程不安全的类)
没有用内置锁,这是因为需要可重入

  • threadFactory 线程池利用threadFactory新建线程。

  • corePoolSize 线程池中的核心线程数,线程池中可用线程的最小数。

  • largestPoolSize 线程池核心最大线程数,线程池中可用线程的最大数。

  • keep-alive time 核心线程允许空转的最长时间。当线程池中的线程数量>corePoolSieze空转的线程超过keep-alive time后会被terminated。

  • workers 线程池工作线程的HashSet集合,包含了线程池执行任务的线程

HashSet线程不安全因此每次在访问这个成员变量时需要获取ReentrantLock

重要方法

execute()

execute用于尝试接收用户提交的任务,并执行拒绝策略。


execute逻辑流程

addWorker()

addWorker用于执行用户提交的任务。首先检查线程池状态,线程池只有在Running状态和阻塞队列不为空的情况下才会执行任务,否则直接返回。
具体处理逻辑如下图所示


image.png

疑问

  • 线程池利用ReentrantLock保证线程安全,为什么在每个方法内部需要final ReentrantLock mianLock重新引用呢?
public long getTaskCount() {
    final ReentrantLock mainLock = this.mainLock;//这里为什么一定要再次引用一下呢??
    mainLock.lock();
    try {
        long n =completedTaskCount;
        for (Worker w :workers) {
            n += w.completedTasks;
            if (w.isLocked())
              ++n;
        }
        return n +workQueue.size();
    }finally {
        mainLock.unlock();
    }
}

相关文章

网友评论

      本文标题:ThreadPoolExecutor线程池

      本文链接:https://www.haomeiwen.com/subject/byuvfktx.html