线程池原理源码

Redorblack

线程池调用execute提交任务—>创建Worker(设置属性thead、firstTask)—>worker.thread.start()—>实际上调用的是worker.run()—>线程池的runWorker(worker)—>worker.firstTask.run();

执行流程

runWork方法 核心(线程复用)

final void runWorker(Worker w) {
    //获取当前线程
    Thread wt = Thread.currentThread();
    //获取w的firstTask
    Runnable task = w.firstTask;
    //设置w的firstTask为null
    w.firstTask = null;
    // 释放锁,设置AQS的state为0,允许中断
    w.unlock();
    //用于标识线程是否异常终止,finally中processWorkerExit()方法会有不同逻辑
    boolean completedAbruptly = true;
    try {
        //循环调用getTask()获取任务,不断从任务缓存队列获取任务并执行
        while (task != null || (task = getTask()) != null) {
            //进入循环内部,代表已经获取到可执行的任务,则对worker对象加锁,保证线程在执行任务过程中不会被中断
            w.lock();
            if ((runStateAtLeast(ctl.get(), STOP) ||  //若线程池状态大于等于STOP,那么意味着该线程要中断
                    (Thread.interrupted() &&      //线程被中断
                            runStateAtLeast(ctl.get(), STOP))) &&  //且是因为线程池内部状态变化而被中断
                    !wt.isInterrupted())           //确保该线程未被中断
                //发出中断请求
                wt.interrupt();
            try {
                //开始执行任务前的Hook方法
                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 {
                    //执行任务后的Hook方法
                    afterExecute(task, thrown);
                }
            } finally {
                //置空task,准备通过getTask()获取下一个任务
                task = null;
                //completedTasks递增
                w.completedTasks++;
                //释放掉worker持有的独占锁
                w.unlock();
            }
        }
        completedAbruptly = false;
    } finally {
        //到这里,线程执行结束,需要执行结束线程的一些清理工作
        //线程执行结束可能有两种情况:
        //1.getTask()返回null,也就是说,这个worker的使命结束了,线程执行结束
        //2.任务执行过程中发生了异常
        //第一种情况,getTask()返回null,那么getTask()中会将workerCount递减
        //第二种情况,workerCount没有进行处理,这个递减操作会在processWorkerExit()中处理
        processWorkerExit(w, completedAbruptly);
    }
}

循环取任务 geTask()

private Runnable getTask() {
    //标识当前线程是否超时未能获取到task对象
    boolean timedOut = false;


    for (;;) {
        //获取线程池的控制状态
        int c = ctl.get();
        //获取线程池的运行状态
        int rs = runStateOf(c);


        //如果线程池状态大于等于STOP,或者处于SHUTDOWN状态,并且阻塞队列为空,线程池工作线程数量递减,方法返回null,回收线程
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
            decrementWorkerCount();
            return null;
        }


        //获取worker数量
        int wc = workerCountOf(c);


        //标识当前线程在空闲时,是否应该超时回收
        // 如果allowCoreThreadTimeOut为ture,或当前线程数大于核心池大小,则需要超时回收
        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;


        //如果worker数量大于maximumPoolSize(有可能调用了 setMaximumPoolSize(),导致worker数量大于maximumPoolSize)
        if ((wc > maximumPoolSize || (timed && timedOut))  //或者获取任务超时
                && (wc > 1 || workQueue.isEmpty())) {  //workerCount大于1或者阻塞队列为空(在阻塞队列不为空时,需要保证至少有一个工作线程)
            if (compareAndDecrementWorkerCount(c))
                //线程池工作线程数量递减,方法返回null,回收线程
                return null;
            //线程池工作线程数量递减失败,跳过剩余部分,继续循环
            continue;
        }


        try {
            //如果允许超时回收,则调用阻塞队列的poll(),只在keepAliveTime时间内等待获取任务,一旦超过则返回null
            //否则调用take(),如果队列为空,线程进入阻塞状态,无限时等待任务,直到队列中有可取任务或者响应中断信号退出
            Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take();
            //若task不为null,则返回成功获取的task对象
            if (r != null)
                return r;
            // 若返回task为null,表示线程空闲时间超时,则设置timeOut为true
            timedOut = true;
        } catch (InterruptedException retry) {
            //如果此worker发生了中断,采取的方案是重试,没有超时
            //在哪些情况下会发生中断?调用setMaximumPoolSize(),shutDown(),shutDownNow()
            timedOut = false;
        }
    }
}

ps:线程池工作线程执行任务发生异常如何处理?

processWorkerExit方法

private void processWorkerExit(Worker w, boolean completedAbruptly) {
    // 正常的话再runWorker的getTask方法workerCount已经被减一了
    if (completedAbruptly)
        decrementWorkerCount();
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        // 累加线程的completedTasks
        completedTaskCount += w.completedTasks;
        // 从线程池中移除超时或者出现异常的线程
        workers.remove(w);
    } finally {
        mainLock.unlock();
    }
    // 尝试停止线程池
    tryTerminate();
    int c = ctl.get();
    // runState为RUNNING或SHUTDOWN
    if (runStateLessThan(c, STOP)) {
        // 线程不是异常结束
        if (!completedAbruptly) {
            // 线程池最小空闲数,允许core thread超时就是0,否则就是corePoolSize
            int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
            // 如果min == 0但是队列不为空要保证有1个线程来执行队列中的任务
            if (min == 0 && !workQueue.isEmpty())
                min = 1;
            // 线程池还不为空那就不用担心了
            if (workerCountOf(c) >= min)
                return; // replacement not needed
        }
        // 1.线程异常退出
        // 2.线程池为空,但是队列中还有任务没执行,看addWoker方法对这种情况的处理
        addWorker(null, false);
    }
}
阅读 107

后端菜鸟记录美好生活

39 声望
0 粉丝
0 条评论
你知道吗?

后端菜鸟记录美好生活

39 声望
0 粉丝
宣传栏