ThreadPoolExecutor一些原理问题

来源:互联网 发布:兰州招聘seo 编辑:程序博客网 时间:2024/05/21 07:23

今天被同事问到,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
原创粉丝点击