线程池的学习笔记以及源码解读

一、创建线程的方式

1.继承Thread类
2.实现Runnable接口
3.实现Callnable接口(有返回值,可抛出异常)
4.线程池
Java提供了Executors可以去创建(规范中不允许使用这种方式创建线程池,这种方式对线程的控制力度比较低)
推荐手动创建线程池

线程池创建方法

	线程池的创建方式总共包含以下 7 种(其中 6 种是通过 Executors 创建的,1 种是通过 ThreadPoolExecutor 创建的):

Executors.newFixedThreadPool():创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待;
Executors.newCachedThreadPool():创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收多余的线程,若线程数不够,则新建线程;
Executors.newSingleThreadExecutor():创建单个线程数的线程池,它可以保证先进先出的执行顺序;
Executors.newScheduledThreadPool():创建一个可以执行延迟任务的线程池;
Executors.newSingleThreadScheduledExecutor():创建一个单线程的可以执行延迟任务的线程池;
Executors.newWorkStealingPool():创建一个抢占式执行的线程池(任务执行顺序不确定)JDK 1.8 添加
ThreadPoolExecutor:最原始的创建线程池的方式,它包含了 7 个参数可供设置
单线程池的意义: 虽然 newSingleThreadExecutor 和 newSingleThreadScheduledExecutor 是单线程池,但提供了工作队列,生命周期管理,工作线程维护等功能。

二、线程池的七个参数

public ThreadPoolExecutor(int corePoolSize,  // 核心线程数
                          int maximumPoolSize, // 最大线程数
                          long keepAliveTime,  // 最大空闲时间
                          TimeUnit unit,  // 时间单位
                          BlockingQueue<Runnable> workQueue,  // 阻塞队列
                          ThreadFactory threadFactory, // 线程工厂
                          RejectedExecutionHandler handler // 拒绝策略
                          )

三、线程池流程

![[Pasted image 20231213202759.png]]

四、线程池属性标识

//是一个int类型的数值,表达了两个意思,1:声明当前线程池的状态 2:声明线程池中的线程数
//高3位:线程池状态  第29位是:线程池中的个数
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));  
private static final int COUNT_BITS = Integer.SIZE - 3; // 32-3 = 29 
private static final int COUNT_MASK = (1 << COUNT_BITS) - 1;  //0001111111111111111111最大容量
  
// runState is stored in the high-order bits  
private static final int RUNNING    = -1 << COUNT_BITS;  //111 代表线程池位RUNNING状态,正常接收任务
private static final int SHUTDOWN   =  0 << COUNT_BITS; 
//000 代表线程池位SHUTDOWN状态,不接收新任务,但是内部还会处理阻塞队列中的任务,正在进行的任务也正常处理
private static final int STOP       =  1 << COUNT_BITS;
//001 代表线程池位STOP状态,不接收新人券,也不去处理阻塞队列中的任务,同时会中断正在执行的任务
private static final int TIDYING    =  2 << COUNT_BITS;  
//010 代表线程池位TIDYING状态,过渡的状态,代表当前的线程池即将结束
private static final int TERMINATED =  3 << COUNT_BITS;  
//011 代表线程池位TERMINATED,要执行terminated(),线程池结束
  
// Packing and unpacking ctl  
private static int runStateOf(int c)     { return c & ~COUNT_MASK; }  //得到线程池的状态
private static int workerCountOf(int c)  { return c & COUNT_MASK; }  //得到当前线程池的线程数量(正在工作的线程)
private static int ctlOf(int rs, int wc) { return rs | wc; }

4.2线程池状态变化

在这里插入图片描述

五、线程池的Execute方法执行

从execute方法开始

public void execute(Runnable command) {  
//健壮性判断
    if (command == null)  
        throw new NullPointerException();  
//拿到32位的int
  int c = ctl.get();  
  //获取工作线程数 <核心线程数
    if (workerCountOf(c) < corePoolSize) {  
    //进到if,代表可以创建核心线程
    //A,B
        if (addWorker(command, true))  
            return;   
        //创建核心线程数失败,重新获取ctl
        c = ctl.get();  
    }  
    //判断线程池是不是Running,将任务添加到阻塞队列中
    if (isRunning(c) && workQueue.offer(command)) { 
    //再次过去ctl 
        int recheck = ctl.get();  
        //再次判断是否是RUNNING,如果不是,移除任务
        if (! isRunning(recheck) && remove(command))  
            reject(command);  //拒绝策略
            //如果线程池处在RUNNING状态,但是工作线程为0
        else if (workerCountOf(recheck) == 0)  
        //阻塞队列有任务,但是没有工作线程,添加一个任务为空的工作线程处理阻塞队列中的任务
            addWorker(null, false);  
    }  
    // 创建非核心线程处理任务
    else if (!addWorker(command, false))  
        reject(command);  //拒绝策略
}

通过上述源码,掌握了线程池操作的执行流程,再次查看addWorker方法内部做了什么处理

private boolean addWorker(Runnable firstTask, boolean core) {  
    retry:   //标记for循环,内部for跳出外层for循环
    for (int c = ctl.get();;) {  
        // Check if queue empty only if necessary.  
        if (runStateAtLeast(c, SHUTDOWN)  
            && (runStateAtLeast(c, STOP)  
                || firstTask != null  
                || workQueue.isEmpty()))  
            return false;  
  
        for (;;) {  
            if (workerCountOf(c)  
                >= ((core ? corePoolSize : maximumPoolSize) & COUNT_MASK))  
                return false;  
            if (compareAndIncrementWorkerCount(c))  
                break retry;  
            c = ctl.get();  // Re-read ctl  
            if (runStateAtLeast(c, SHUTDOWN))  
                continue retry;  
            // else CAS failed due to workerCount change; retry inner loop  
        }  
    }  
  
    boolean workerStarted = false;  
    boolean workerAdded = false;  
    //Worker就是工作线程
    Worker w = null;  
    try {  
    //创建Worker,传入任务
        w = new Worker(firstTask);  
        //从Worker中获取线程t
        final Thread t = w.thread;  
        if (t != null) {  
        //获取线程池的全局锁,避免添加任务时别的线程干掉了线程池,干掉线程需要先获取这个锁
            final ReentrantLock mainLock = this.mainLock;  
            mainLock.lock();  //加锁
            try {  
                // Recheck while holding lock.  
                // Back out on ThreadFactory failure or if                
                // shut down before lock acquired.                
                int c = ctl.get();  
  
                if (isRunning(c) ||  
                    (runStateLessThan(c, STOP) && firstTask == null)) {  
                    if (t.getState() != Thread.State.NEW)  
                        throw new IllegalThreadStateException();  
                        //工作线程放在hashset中
                    workers.add(w);  
                    workerAdded = true;  
                    int s = workers.size();  
                    if (s > largestPoolSize)  
                        largestPoolSize = s;  
                }  
            } finally {  
                mainLock.unlock();  
            }  
            if (workerAdded) {  
                t.start();  //启动工作线程
                workerStarted = true;  //启动工作线程成功
            }  
        }  
    } finally {  
        if (! workerStarted)  //如果启动工作线程失败
            addWorkerFailed(w);  
    }  
    return workerStarted;  
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值