我们首先创建一个线程池,使用查看submit提交任务的方法,在这里我们以参数为提交callable为例,,线程池的submit方法的实现在AbstractExecutorService中实现,在submit方法中主要做了一下几件事情

java线程池的简单运行过程_工作线程

 

1.参数校验

2.把我们的callable任务封装为一个RunnableFuture(通过newTaskfor方法,返回FutureTask,继承关系如下图)

java线程池的简单运行过程_工作线程_02

 

java线程池的简单运行过程_工作线程_03

 

3.调用线程池的execute方法执行处理任务逻辑

4.返回future

所以线程池如何管理线程处理任务也就是在第三步执行execute方法中,execute方法是顶层接口Executor的方法,具体实现要看实现类。我们经常使用的也就是ThreadPoolExecutor,所以就看ThreadPoolExecutor的execute方法

(继承关系)

 java线程池的简单运行过程_继承关系_04

 //在下面的代码中出现的ctl是一个很重要的字段,它的作用是记录线程池的生命周期和当前工作的线程数,低29位表示工作线程的个数,高三位表示线程池的状态。
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); 1.获取ctl的值 int c = ctl.get();
     2.从ctl的值中获取线程池中线程池的个数,如果小于corePoolSize则使用addWork()方法创建线程执行任务 if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) return; c = ctl.get(); }
3.如果当前工作线程个数大于corePoolSize则判断 线程池在运行状态 并且 任务添加到队列是否成功 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); }
4.线程个数大于corePoolSize且添加任务到任务队列失败,添加非corePoolSize线程,如果小于maxPoolSize,成功,若失败则拒绝 else if (!addWorker(command, false)) reject(command); }

我们创建处理任务的线程可以看出来实在addWorker()方法中进行的

 线程池的五种状态,这五种状态的ctl值按下面排列递增

running:接受新任务并处理排队的任务

SHUTDOWN: 不接受新任务,但处理排队的任务

stop: 不接受新的任务,不处理排队的任务。并中断正在进行的任务

TIDYING。 所有的任务都结束了,workerCount为零。转换到TIDYING状态的线程
TERMINATED: terminated()已经完成

private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
       获得线程池状态 int rs = runStateOf(c); // Check if queue empty only if necessary.
       如果线程池状态>=shutdown 并且 (线程池状态不等于shutdown 或者任务为空或者任务队列为空) 则返回false if (rs >= SHUTDOWN && ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())) return false; for (;;) {
          获取当前工作线程的数量 int wc = workerCountOf(c);
如果线程数量大于等于capacity(线程池允许最大数量)或者线程数量大于核心(最大)线程数则返回false if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize)) return false; if (compareAndIncrementWorkerCount(c))线程池数量+1 break retry; c = ctl.get(); // Re-read ctl if (runStateOf(c) != rs) continue retry; // else CAS failed due to workerCount change; retry inner loop } } boolean workerStarted = false; boolean workerAdded = false; Worker w = null; try {
       真正创建线程的地方,把我们的任务传入进去 w = new Worker(firstTask); final Thread t = w.thread;从创建的Worker中取得创建的线程 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 rs = runStateOf(ctl.get()); if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) { if (t.isAlive()) // precheck that t is startable throw new IllegalThreadStateException(); workers.add(w);//加入线程池管理 int s = workers.size(); if (s > largestPoolSize) largestPoolSize = s; workerAdded = true; } } finally { mainLock.unlock(); } if (workerAdded) { t.start();启动线程 workerStarted = true; } } } finally { if (! workerStarted) addWorkerFailed(w); } return workerStarted; }

  worker代码如下,worker也继承了runable接口,所以重写了run方法Worker(Runnable firstTask) {

            setState(-1); // inhibit interrupts until runWorker
            this.firstTask = firstTask;我们传入的任务
            this.thread = getThreadFactory().newThread(this);从ThreadFactory中获得线程,并且把当前worker(this)传入了进去,所以当该线程start时,调用的也就是当前worker的run方法
        }

 

worker的run方法又调用了runworker(this)方法,所以我们去看runworker方法

java线程池的简单运行过程_线程池_05

 

 final void runWorker(Worker w) {

        Thread wt = Thread.currentThread();创建的线程
        Runnable task = w.firstTask;传入的futureTask任务
        w.firstTask = null;
        w.unlock(); // allow interrupts
        boolean completedAbruptly = true;
        try {
        不断的从任务队列中获取任务 while (task != null || (task = getTask()) != null) { w.lock(); // If pool is stopping, ensure thread is interrupted; // if not, ensure thread is not interrupted. This // requires a recheck in second case to deal with // shutdownNow race while clearing interrupt
          如果线程池正在被停止,要确保线程被终止
          如果没有,确保线程没有被终端
         if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && !wt.isInterrupted()) wt.interrupt(); try { beforeExecute(wt, task); Throwable thrown = null; try { task.run();调用了一开始的futureTask的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; w.completedTasks++; w.unlock(); } } completedAbruptly = false; } finally { processWorkerExit(w, completedAbruptly);
    正常退出后在里面进行线程的rmove工作
    并且会尝试终止线程池
    并且会根据参数配置是否回收核心线程,如果
allowCoreThreadTimeOut为true则回收核心线程
} } 

在这个流程中也解决了我的两个疑惑

1.线程池在创建时就初始化了corePoolSize个线程吗?

我们从源码中可以看出并不是,线程池初始创建的工作线程数为0.可以从ctl字段的初始值看出来。或者是当我们创建worker时,可以看到即便线程数小于corePoolSize,也是通过addWorker去创建新的worker,而不是从集合中取.

2.核心线程不会被回收吗

在最后一步当线程获取不到任务执行processWorkerExit()方法时,会执行workers.remove(worker)方法。如果配置了allowCoreThreadTimeOut为false,那么 会新创建一个没有task的线程。如果allowCoreThreadTimeOut为true,则最小线程数为0

private void processWorkerExit(Worker w, boolean completedAbruptly) {
        if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
            decrementWorkerCount();

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            completedTaskCount += w.completedTasks;
            workers.remove(w);
        } finally {
            mainLock.unlock();
        }

        tryTerminate();

        int c = ctl.get();
        if (runStateLessThan(c, STOP)) {
            if (!completedAbruptly) {
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
                if (min == 0 && ! workQueue.isEmpty())
                    min = 1;
                if (workerCountOf(c) >= min)
                    return; // replacement not needed
            }
            addWorker(null, false);
        }
    }