ThreadPoolExecutor一些原理问题

今天被同事问到,ThreadPoolExecutor是怎么在线程执行后,保存线程的; worker线程去调用具体的业务线程,是不是就启动了两次线程。

平时用的比较多的是用ExecutorService 来创建newCachedThreadPool(), newFixedThreadPool(), SingleThreadExecutor()

看了一下源代码,这几个建线程池的方法都是创建ThreadPoolExecutor


  public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) 

corePoolSize就是运行的核心线程的数,maximumPoolSize就是最大线程数,keepAliveTime是空闲线程的等待时间,workQueue是用来存放等待线程的。

当poolSize<corePoolSize时,每新来一个任务,则会创建一个工作线程(worker)来处理当前的任务, worker 处理完第一个线程后,会处理queue里的线程。worker在keepAliveTime的时间内,如果没有收到新的任务,则该worker会消失


1. ThreadPoolExecutor是怎么在线程执行后,一直保留worker线程(小于corePoolSize)存活的?

答案在getTask方法的代码里:

Runnable getTask() {
        for (;;) {
            try {
                int state = runState;
                if (state > SHUTDOWN)
                    return null;
                Runnable r;
                if (state == SHUTDOWN)  // Help drain queue
                    r = workQueue.poll();
                else if (poolSize > corePoolSize || allowCoreThreadTimeOut)
                    r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS);
                else
                    r = workQueue.take();
                if (r != null)
                    return r;
                if (workerCanExit()) {
                    if (runState >= SHUTDOWN) // Wake up others
                        interruptIdleWorkers();
                    return null;
                }
                // Else retry
            } catch (InterruptedException ie) {
                // On interruption, re-check runState
            }
        }
    }

当前的线程数<corePoolSize时, workerCanExit()返回false, 无条件循环到   r = workQueue.take();  take是阻塞方法 ,因此work的线程会一直等待,   不会退出, 等到queue里任务后再执行。


2. worker线程去调用具体的业务线程,是不是就启动了两次线程
注意: worker线程会去调用任务线程里的run方法。而不是start方法。从而避免了多次创建线程

private void runTask(Runnable task) {
            final ReentrantLock runLock = this.runLock;
            runLock.lock();
            try {
                /*
                 * Ensure that unless pool is stopping, this thread
                 * does not have its interrupt set. This requires a
                 * double-check of state in case the interrupt was
                 * cleared concurrently with a shutdownNow -- if so,
                 * the interrupt is re-enabled.
                 */
                if (runState < STOP &&
                    Thread.interrupted() &&
                    runState >= STOP)
                    thread.interrupt();
                /*
                 * Track execution state to ensure that afterExecute
                 * is called only if task completed or threw
                 * exception. Otherwise, the caught runtime exception
                 * will have been thrown by afterExecute itself, in
                 * which case we don't want to call it again.
                 */
                boolean ran = false;
                beforeExecute(thread, task);
                try {
                    task.run();
                    ran = true;
                    afterExecute(task, null);
                    ++completedTasks;
                } catch (RuntimeException ex) {
                    if (!ran)
                        afterExecute(task, ex);
                    throw ex;
                }
            } finally {
                runLock.unlock();
            }
        }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值