线程并发-ThreadPoolExcutor 原理实解

一、ThreadPoolExcutor 结构

    

 

 

 

 

二、源码分析

/*----------------------------1.提交任务----------------------------------*/
void execute(Runnable command):

/*如果workerSet中工作线程数 小于 corePoolSize 则直接创建新的 Worker对象,并添加至 workerSet 中,然后启动 Worker对象 中的线程*/
if (workerCountOf(c) < corePoolSize) {
    if (addWorker(command, true))
        return;
    c = ctl.get();
}
/*如果 workerSet中线程 全部运行 且 线程数大于等于corePoolSize ,任务添加至阻塞队列workQueue*/
if (isRunning(c) && workQueue.offer(command)) {
    int recheck = ctl.get();
    if (! isRunning(recheck) && remove(command))
        reject(command);
    else if (workerCountOf(recheck) == 0)
        addWorker(null, false);
}
/*如果 workQueue 添加任务失败(队列已满),添加非核心线程。如果非核心线程添加失败(工作线程数wc >= maxinumPoolSize),则执行拒绝策略*/
else if (!addWorker(command, false))
    reject(command);


/*---------------------------- 2.添加任务&&创建线程----------------------------------*/
boolean addWorker(Runnable firstTask, boolean core):
...
/**
 * 添加任务失败的情况:
 * 1. core=true:添加核心任务线程,如果当前工作线程数wc 大于等于 corePoolSize 则核心任务线程添加失败,返回false
 * 2. core=false: 添加非核心任务,如果工作线程数wc 大于等于 maxinumPoolSize 则非核心任务添加失败,返回false
 */
if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize))
    return false;
...
/*创建新的Worker:新的线程和任务*/
w = new Worker(firstTask);
final Thread t = w.thread;
...
/*worker 添加到 workerSet*/
workers.add(w);
...
/*启动worker 中的线程:线程启动后执行run()方法中的runWorker()方法*/
t.start();


/*----------------------------3.运行worker----------------------------------*/
final void runWorker(Worker w):
/**
 * 创建的Worker线程在while循环中会不停的获取任务进行执行,直到获取的任务为空时循环结束,将线程从workerSet中移除,线程销毁。需注意以下情况:
 * 1. 设置keepAliveTime 超时时间的线程,在获取不到任务时返回null,则线程会终止(这种情况叫做非核心线程)
 * 2. 没有设置keepAliveTime 超时时间的线程会阻塞直到获得任务,所以会一直在 while循环中,不会退出(一遍情况叫做核心线程)
 */
try{
    /* 不停的获取任务并进行执行,直到获取的任务为null */
    while (task != null || (task = getTask()) != null) {
        ...
        task.run();
        ...
    }
}finally {
    /*获取到任务为 null 时进行线程清理工作:将当前worker从workerSet中移除,线程结束*/
    processWorkerExit(w, completedAbruptly);
}

/*----------------------------4.worker运行中获取任务----------------------------------*/
Runnable getTask():

/**
 * ThreadPoolExcutor 中并未区分核心和非核心线程数,为了便于理解将 小于corePoolSize 时创建的线程叫核心线程,大于corePoolSize创建的线程叫非核心线程
 * 线程是否空闲超时销毁:
 * 1.如果设置了 allowCoreThreadTimeOut=true ,则核心线程数也会超时销毁(workerSet集合中的Worker都相同)
 * 2.如果 allowCoreThreadTimeOut=false,则只有 大于corePoolSize的线程会超时销毁(获取任务时满足:wc > corePoolSize 条件时,获取任务为null 的线程就会销毁,可以认为是非核心线程)
 */
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

try {
    Runnable r = timed ?
        // 从队列中获取任务,超时则返回null(一般情况下将此处认为是非核心线程)
        workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
        // 阻塞从队列中获取任务,直到获取成功为止(一般情况下将此处认为是核心线程,一直在不停的进行任务的获取和执行,不会销毁)
        workQueue.take();
    if (r != null)
        return r;
    timedOut = true;
} catch (InterruptedException retry) {
    timedOut = false;
}

 

三、流程分析(待完善...)

 

posted @ 2023-03-24 11:32  蓝迷梦  阅读(46)  评论(0)    收藏  举报