线程池核心源码

1. 线程池7大参数

1.0 线程池工作原理

//存放工作线程的集合
private final HashSet workers = new HashSet();
//代表一个工作线程
Worker
worker 实现runnable接口 代表可执行任务
—属性:
1. final Thread thread // 具体工作的线程
2. Runnable firstTask // 需要执行的任务
-----a
自己语言描述
worker 线程池工作的核心类
线程池每当创建一个工作线程,实际上就是创建一个worker类,worker 里面有2个属性 thread,和Runnable,用thread 来执行runworker方法,runworker方法执行 提交的任务。任务执行完后,runworker方法不会停止,使用while循环不断的区任务队列里面获取任务。

worker 类在addworker方法里面 创建对象,执行start方法。

 ExecutorService threadPoolExecutor = new ThreadPoolExecutor(2, 2,
                60, TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(2),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy());

1.6 线程池工厂

给线程该名称-线程工厂

1.7 线程池拒绝策略

多线程四种拒绝策略
这四种拒绝策略,在ThreadPoolExecutor是四个内部类。

AbortPolicy abortPolicy = new ThreadPoolExecutor.AbortPolicy();
DiscardPolicy discardPolicy = new ThreadPoolExecutor.DiscardPolicy();
DiscardOldestPolicy discardOldestPolicy =new ThreadPoolExecutor.DiscardOldestPolicy();
CallerRunsPolicy callerRunsPolicy = new ThreadPoolExecutor.CallerRunsPolicy();

  1. AbortPolicy

当任务添加到线程池中被拒绝时,直接丢弃任务,并抛出

RejectedExecutionException异常。

  1. DiscardPolicy

当任务添加到线程池中被拒绝时,丢弃被拒绝的任务,不抛异常。

  1. DiscardOldestPolicy

当任务添加到线程池中被拒绝时,丢弃任务队列中最旧的未处理任务,然后将被拒绝的任务添加到等待队列中。

  1. CallerRunsPolicy

被拒绝任务的处理程序,直接在execute方法的调用线程中运行被拒绝的任务。

总结:就是被拒绝的任务,直接在主线程中运行,不再进入线程池。

2.线程池执行流程

proce

3.ThreadPoolExecutor状态

3.1 ctl

//int 类型的数值
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
//	Integer.SIZE=32
//ctl 表示两种状态
//1.表示线程池当前的工作状态(高三位)
//2.表示线程池当前的工作线程数(低29位)
    private static final int COUNT_BITS = Integer.SIZE - 3;//29
    //工作线程最大容量
    //00011111 11111111 11111111 11111111
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
//1<<29  00100000 00000000 00000000 00000000 
//1<<29-1 0001111 11111111 11111111 11111111
    // runState is stored in the high-order bits
    // 线程池的五种状态
    // -1 -> 11111111 11111111 11111111 11111111
    // -1<<29 11100000 00000000 00000000 00000000 
    private static final int RUNNING    = -1 << COUNT_BITS;
    //000
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    //001 ...
    private static final int STOP       =  1 << COUNT_BITS;
    //010 ...
    private static final int TIDYING    =  2 << COUNT_BITS;
    //110 ...
    private static final int TERMINATED =  3 << COUNT_BITS;
     // Packing and unpacking ctl
     //计算出当前线程池的状态
     // ~CAPACITY -> 11100000 00000000 00000000 00000000
    private static int runStateOf(int c)     { 
    	return c & ~CAPACITY; }
    // 计算当前线程池的数量
    private static int workerCountOf(int c)  { 
    //00011111 11111111 11111111 11111111
    	return c & CAPACITY; }
  // rs 为高 3 位代表线程池状态, wc 为低 29 位代表线程个数,ctl 是合并它们
    private static int ctlOf(int rs, int wc) { 
    	return rs | wc; }

3.2 线程池状态过程

11
terminated tidying stop shutdown running

4 线程池 核心方法

4.1 execute()

为什么线程池为添加一个空任务的非核心线程
为了解决 工作线程为0,但是工作队列有任务i的状态

public void execute(Runnable command) {
	//非空判断
        if (command == null)
            throw new NullPointerException();
        //获取ctl属性
        int c = ctl.get();
        // 获取线程池工作线程的个数 是否小于核心线程
        if (workerCountOf(c) < corePoolSize) {
 		//添加一个任务让核心线程执行
            if (addWorker(command, true))
            //成功 返回true
                return;
             // 添加任务让核心线程执行失败,比如多个线程并发情况下
             // 都执行execute
             // 只有一个成功 那么重新获取ctl 
            c = ctl.get();
        }
        //创建核心线程失败
        // 判断当前线程池的状态是否running 是 && 将任务添加到任务队列
        if (isRunning(c) && workQueue.offer(command)) {
        //添加任务到工作队列成功 重新获取ctl
            int recheck = ctl.get();
        // 判断线程池是否是running
        // 不是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);
    }

4.2 addWorker()

// 添加核心线程处理任务
工作队列有任务,但是没有工作线程 ,添加非核心线程处理工作队列的任务
添加非核心线程处理任务

功能 添加工作线程到workers set集合中 并启动工作线程 start ,

  1. 判断线程池状态 和线程工作数量
  2. 添加工作线程,并启动工作线程
private boolean addWorker(Runnable firstTask, boolean core) {
        //break 内层 跳出外层for循环
        retry:
//------------
//对线程池状态的判断,以及对工作线程数量的判断
        for (;;) {
        	//获取ctl
            int c = ctl.get();
            //获取线程池状态
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
  		// rs >= SHUTDOWN 当前线程不是running, running 属性小于0 
  		//查看当前任务是否可以不处理        
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
           //线程池状态为 shutdown,任务为null,并且工作队列不为空
           //如果同时满足这三个要求,那么就要 处理工作队列中的任务
           // 不是running状态,不处理新任务 false
           //如果满足 shutdown状态,满足之前addWorker(null,false)
           //并且工作队列有任务,不走false 
                return false;

			//for 循环 开始判断数量
            for (;;) {
            // 获取工作线程数量
                int wc = workerCountOf(c);
                // 判断工作线程是否大于最大值 
                if (wc >= CAPACITY ||
                //如果是核心 是否大于corePoolSize
                // 如果是非核心线程,是否大于 最大线程数 
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    //当前工作线程 已经达到最大值
                    return false;
                    // cas 自增工作线程数量
                if (compareAndIncrementWorkerCount(c))
                // 成功跳出外出for循环,走下面的代码添加工作线程
                    break retry;
                 // cas 失败,有并发操作。
                c = ctl.get();  // Re-read ctl
              //基于寻获取的线程状态,判断和之前的rs状态是否一致
                if (runStateOf(c) != rs)
         //不一致,需要重新判断线程状态,continue 到外层for循环中
                    continue retry;
		// 线程装填一致,在内层for 中继续 判断工作线程数量
                // else CAS failed due to workerCount change; retry inner loop
            }
        }
 //-------------


//添加工作线程,并启动工作线程
//工作线程是否启动
        boolean workerStarted = false;
        //工作线程是否添加
        boolean workerAdded = false;
        // 工作线程
        Worker w = null;
        try {
           //构建工作线程,并将任务 扔到工作线程中
            w = new Worker(firstTask);
          // 拿到worker中绑定的线程
            final Thread t = w.thread;
            //创建工作线程成功
            if (t != null) {
            //加锁 线程池中已有的锁 锁定整个线程池
            // 防止在添加工作线程时,其他线程执行shutdown 等方法。
                final ReentrantLock mainLock = this.mainLock;
                mainLock.lock();
                try {
                    // Recheck while holding lock.
                    // Back out on ThreadFactory failure or if
                    // shut down before lock acquired.
                 //基于重新获取的ctl 判断线程池的状态
                 // 类似于双检操作, ctl状态在上面,
                 //在上面一段代码--没获取锁中ctl发改变  需要重新判断
                    int rs = runStateOf(ctl.get());
				//rs<shutdown  running 状态
				//线程池状态为shutdown,并且传入的任务为null 
				//为了考虑  工作线程为0,队列中有任务 
                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                    //判断当前线程是否处于run状态 (健壮性判断 )
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();
                  // workers -》hashset 
                  // 将构建好的worker对象添加到set中
                        workers.add(w);
                        // 当前工作线程
                        int s = workers.size();
                        //或者历史 工作线程最大值
                        if (s > largestPoolSize)
                        //线程工作线程数大于 历史最大工作线程数
                            largestPoolSize = s;
                         //完成工作线程添加,标识设置为true
                        workerAdded = true;
                    }
                } finally {
                ///---添加工作线程数
                    mainLock.unlock();
                }
                if (workerAdded) {
                //工作线程添加成功,启动线程
                    t.start();
                 //工作线程启动标识设置为true
                    workerStarted = true;
                }
            }
        } finally {
        //启动工作线程失败 
            if (! workerStarted)
            // 移除set 中的work 工作线程数量-1,修改线程池状态为tidying
                addWorkerFailed(w);
        }
        return workerStarted;
    }
//启动工作线程失败后的操作
 private void addWorkerFailed(Worker w) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
        //判断之前创建工作线程是否成功,
            if (w != null)
            // 如果成功 将当前工作线程 从 set中移除
                workers.remove(w);
           // 对应之前cas 工作线程数+1方法 工作线程数量-1
            decrementWorkerCount();
            // 尝试线程池状态变为didying
            tryTerminate();
        } finally {
            mainLock.unlock();
        }
    }

4.3 worker 对象

中断线程不是立即让线程停止,只是标记了thread的中断标识为true
核心内容
线程对象在里面
任务在里面 //需要执行的任务 来源1.传进来直接执行 2. 阻塞队列获取
初始化线程,不允许被中断 state=-1

 private final class Worker
        extends AbstractQueuedSynchronizer // 处理线程中断问题
        implements Runnable //存储需要执行的任务
    {
   // 工作线程的thread对象,在初始化就创建了
        final Thread thread;
   	//需要执行的任务 来源1.传进来直接执行 2. 阻塞队列获取
        Runnable firstTask;
        volatile long completedTasks;

        Worker(Runnable firstTask) {
        //当前工作线程刚刚被初始化,不允许被中断  执行runwoker
            setState(-1); // inhibit interrupts until runWorker
            // 任务复制
            this.firstTask = firstTask;
            this.thread = getThreadFactory().newThread(this);
        }
		//runnable 方法, 调用t.start()时,执行的run方法
        public void run() {
            runWorker(this);
        }
        protected boolean isHeldExclusively() {
            return getState() != 0;
        }

        protected boolean tryAcquire(int unused) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }
		// 将sate 置为0 为了表示当前线程运行被中断 
        protected boolean tryRelease(int unused) {
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        public void lock()        { acquire(1); }
        public boolean tryLock()  { return tryAcquire(1); }
        public void unlock()      { release(1); }
        public boolean isLocked() { return isHeldExclusively(); }

        void interruptIfStarted() {
            Thread t;
            if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
                try {
                    t.interrupt();
                } catch (SecurityException ignore) {
                }
            }
        }
    }

4.4 runworker()

//执行任务流程 中断相关
执行任务

    final void runWorker(Worker w) {
        //拿到当前线程 也就是worker线程
        Thread wt = Thread.currentThread();
        // worker对象里面的任务
        Runnable task = w.firstTask;
        w.firstTask = null;
        //state =0
        w.unlock(); // allow interrupts
        // 任务执行时,钩子函数是否出异常, 出异常为true
        //没出异常 变为false
        boolean completedAbruptly = true;
        try {
        //获取任务方式1 执行execute或者submit时 直接执行
        //方式2 从工作队列拿任务执行
            while (task != null || (task = getTask()) != null) {
            // 加锁 在shutdown状态下,当前线程不允许中断 
            // state 0  1 
                w.lock();
	// 判断线程池状态 为 STOP状态,stop,那么必须将当前线程中断
     //第一个判断 判断当前线程池状态是否为STOP
                if ((runStateAtLeast(ctl.get(), STOP) ||
             // 当前线程池不是sotp,查询当前线程是否被中断,并置为false
       		//如果为false,不是stop状态,
       		//如果为true,需要再次查看是否时并发操作导出线程池为STOP
                     (Thread.interrupted() &&
    				//查看
                      runStateAtLeast(ctl.get(), STOP)))
                       &&
                     // 查询当前线程是否以及被中断 
                    !wt.isInterrupted())
               //中断标志位 true
                    wt.interrupt();
		///----具体执行任务
                try {
                // 执行任务的钩子函数
                    beforeExecute(wt, task);
                    Throwable thrown = null;
                    try {
                    // 执行任务
                        task.run();
                        //内部吃异常
                    } catch (RuntimeException x) {
                        thrown = x; throw x;
                    } catch (Error x) {
                        thrown = x; throw x;
                    } catch (Throwable x) {
                        thrown = x; throw new Error(x);
                    } finally {
                    // 执行完之后的处理
                        afterExecute(task, thrown);
                    }
                } finally {
                //任务执行完毕 task置为null
                    task = null;
                    // 执行成功任务个数加1
                    w.completedTasks++;
                    //state 置为0 干完活了
                    w.unlock();
                }
            }
            completedAbruptly = false;
        } finally {
            processWorkerExit(w, completedAbruptly);
        }
    }

4.5 getTask()

如何从工作队列拿到任务
getTask() 从阻塞队列里拿到任务
//判断工作状态 不是shutdown等状态
//判断 工作线程数量是否大于核心线程 &&当前线程是否达到最大生存时间 && 工作线程数>! || 队列为空

 private Runnable getTask() {
    boolean timedOut = false; // Did the last poll() time out?

    for (;;) {
	    //======================判断线程池状态========================
        int c = ctl.get();
        int rs = runStateOf(c);

        // Check if queue empty only if necessary.
        //、线程池状态大于等于shutdown (shutdown stop)
        // 并且 . 线程池状态大于等于stop || 线程池状态为shutdown ,工作队列为空
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
	        //减去工作线程数量。 worker移除set集合 在processWorkerExit方法中 
            decrementWorkerCount();
            return null;
        }
	//======================判断工作线程数量=======================
        int wc = workerCountOf(c);
//(一般不设置 false) allowCoreThreadTimeOut允许核心超时吗(默认false) 如果true 使用keepalive 超时
 // 工作线程是否大于核心线程 如果大于核心线程, 需要超时 干掉多的
        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

        if (
        //工作线程大于最大线程 
  // ||(timed->ture(工作线程数大于核心线程数)&&timedOut->true( 当前线程在队列中阻塞超时))
        (wc > maximumPoolSize || (timed && timedOut))
		//工作线程数 >1 || 工作队列为空
            && (wc > 1 || workQueue.isEmpty())) {
	    // 减去当前工作线程  worker移除set集合 在processWorkerExit方法中 
            if (compareAndDecrementWorkerCount(c))
                return null;
            continue;
        }
	// 从工作队列中获取任务======
        try {
	        //timed 工作线程大于核心线程 
            Runnable r = timed ?
            // 非核心线程 阻塞救急线程存活时间,来获取任务
                workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
			// 核心线程一直阻塞
                workQueue.take();
            if (r != null)
            //拿到任务返回
                return r;
         //从队列获取任务超时,达到当前工作线程的最大生存时间
            timedOut = true;
        } catch (InterruptedException retry) {
            timedOut = false;
        }
    }
}

4.6 processWorkerExit()

移除工作线程
记录移除工作线程执行多少任务
尝试改变线程池工作状态
线程池状态不是stop 状态下 :
工作队列还有值
队列有任务需要添加一个非核心线程 处理任务

/**
执行 1.当前工作线程数量达到一定程度那么返回null 在finally 执行这个 
     2. 当前线程池状态 不太对, 移除工作线程
*/
private void processWorkerExit(Worker w, boolean completedAbruptly) {
	// 工作线程执行 钩子函数是否出异常, 出异常为true  true出现中
	//执行这个方法不是因为getTask返回null引起的,而是因为钩子函数 出现异常引起的 
    if (completedAbruptly) 
    //因为执行方式 “不合法” 手动扣减工作线程数
        decrementWorkerCount();

    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
	    // completedTaskCount 记录当前线程池一共处理了多少任务
        completedTaskCount += w.completedTasks;
        //异常工作线程
        workers.remove(w);
    } finally {
        mainLock.unlock();
    }

	// 尝试改变线程池状态 到过渡状态--- 销毁状态
    tryTerminate();

	// 获取属性
    int c = ctl.get();
    // 当前线程池状态 <stop  不是sto状态   (shutdown running)
    if (runStateLessThan(c, STOP)) {
	    //(shutdown running)
        if (!completedAbruptly) {
	     // 正常执行gettask,移除当前工作线程返回 就执行逻辑 
	     // 核心线程数最小值 为 多少
            int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
            //core为0,工作队列不为空
            if (min == 0 && ! workQueue.isEmpty())
			//设置工作线程为1
                min = 1;
            //还有工作线程在线程中 就直接return 
            if (workerCountOf(c) >= min)
                return; // replacement not needed
        }
        // 不正常方式移除工作线程 在添加一个,
        //或者线程池工作队列不为空,且没有工作线程 也需要添加一个工作线程
        addWorker(null, false);
    }
}

5 线程池循环使用

第一:为什么线程池中的线程可以复用 — 是因为线程池中的线程执行的是Worker的Run方法,而这里面是一个相当于 while(true)的死循环,因此线程永远不会有执行完的那一天
 第二:为什么不会被回收 — 是因为存在GC ROOT 的引用,所以无法被回收 。 引用如下
          ThreadPoolExecutor -> Worker -> Thread
         由于Thread 是 活着的,因此可作为GC ROOT ,所以才会看到 局部线程池ThreadPoolExecutor没有被释放

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
线程池(ThreadPoolExecutor)是 Java 中用于管理和执行线程的机制。下面是ThreadPoolExecutor源码的剖析: ```java public class ThreadPoolExecutor extends AbstractExecutorService { // 省略其他成员变量 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { // 根据参数创建线程池 } // 省略其他构造方法和方法重载 public void execute(Runnable command) { // 执行任务,将任务提交给线程池进行处理 } // 省略其他方法 private void runWorker(Worker w) { // 工作线程执行具体任务的逻辑 Runnable task = w.firstTask; w.firstTask = null; boolean completedAbruptly = true; try { while (task != null || (task = getTask()) != null) { // 执行任务 task.run(); task = null; } completedAbruptly = false; } finally { processWorkerExit(w, completedAbruptly); } } // 省略其他内部类和方法 } ``` 上述代码展示了ThreadPoolExecutor的主要结构。它是一个实现了ExecutorService接口的具体类,在Java中用于执行和管理线程池。 在构造方法中,我们可以设置核心线程数(corePoolSize)、最大线程数(maximumPoolSize)、空闲线程的存活时间(keepAliveTime)、时间单位(unit)和阻塞队列(workQueue)等参数。 execute方法用于向线程池提交任务,任务将被封装成一个Runnable对象,然后由线程池中的工作线程执行。 runWorker方法被工作线程调用,用于执行具体的任务逻辑。它不断地从阻塞队列中获取任务并执行,直到阻塞队列为空或工作线程被中断。 这只是ThreadPoolExecutor源码的简要剖析,了解更多细节可以查看源码实现。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值