Java线程池ThreadPoolExecutor中workers.remove(w)疑惑

新手上路,请多包涵

在查看Java线程池实现的源码时,对于线程池内部worker生命周期有一个不解的地方:当worker所持有的task,或者线程队列中的task都被执行完以后,为什么worker要被移除线程池的worker集合。

追踪源码的过程大致是:
查看execute(Runnable command)方法,发现了addWorker(command, true)的调用

        int c = ctl.get();
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        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);
        }
        else if (!addWorker(command, false))
            reject(command);

进入addWorker(Runnable firstTask, boolean core),发现了worker线程的启动

if (workerAdded) {
    t.start();
    workerStarted = true;
}

Worker类的run方法即调用ThreadPoolExecutor中的runWorker方法。
在runWorker方法的最后调用了processWorkerExit方法。

} finally {
    processWorkerExit(w, completedAbruptly);
}

在processWorkerExit中发现:

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

worker被从线程集合workers移除了。

所以疑惑或者问题是:
线程持中其实是不保有一定数量可用线程,如果当task队列里面没有要处理的任务,原先创造的worker工作线程都会逐步被移除,直到下次再有新的task到来,才又会创建新的worker工作线程??

阅读 6k
3 个回答

图片描述
题主可以点进去getTask方法里面看下,runWorker的while循环提交里面
1.timedOut[1040], 首次获取任务是否可以超时, 默认false
2.[1043-1050], 检查线程池状态, 如果处于关闭状态则返回null。根据代码,会关闭所有线程
3.timed ,允许超时?[1055], 是否允许核心线程超时 || 当前活动线程是否大于核心线程
4.[1057-1062]。 分成两段,同时为真才会执行[1059]-[1061]

   4.1 当前活动线程是否大于maximumPoolSize || 允许超时
   4.2 活动线程大于 1 条 || 任务队列为空的

5.[1065-1070]根据timed参数, 是有永久阻塞获取任务

简单的来说就是,线程池会维持corePoolSize条线程存活持续等待任务。当任务队列满了,但活跃线程数小于maximumPoolSize,线程池就会去创建额外的线程去执行任务。当任务队列空了,线程池只会保留corePoolSize条线程,额外线程就会被杀死

图片的源代码是jdk1.8, 我说的可能比较粗糙。题主可以去看下这篇文章

没有task时候,worker会堵塞在blockingqueue的take的 ,并不会执行下面的方法 那个只有pool的statue处于stop或terminated时候色处理操作

线程池会自己先建立指定的数量,当使用的时候调用其中的线程,当线程超过指定的数据时,会创建额外的线程,使用完了后,一定时候没有使用,会回收,回收完后,当回收到线程池中剩下指定的数量后,不再回收,额外的线程会被回收。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题