【ThreadPoolExecutor】源码阅读

一、生命周期

1)项目中是创建线程池的代码如下:

private ExecutorService accountDeleteExecutor = new ThreadPoolExecutor(
    // corePoolSize
    2, 

    // maximumPoolSize 
    Runtime.getRuntime().availableProcessors()*2, 
   
    // keepAliveTime
    0L, 
   
    // unit
    TimeUnit.MILLISECONDS,

    // workQueue
    new LinkedBlockingQueue<Runnable>(),
    
    // threadFactory
    new NamedThreadFactory("account_delete")
);

创建线程池源码分析:

/**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters.
    

     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
        保持在线程池中的核心线程数量,也就是即使是空闲,也会保留下来不销毁。
        当然了,除非设置了:allowCoreThreadTimeout参数。


     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     允许保留在线程池中的最大线程的数量。
     理解:随着任务的增多线程是会不断添加,但是总得有个上限吧,这个就是啦!!!



     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     如果线程池中的线程大于核心数量,超过核心数的空闲线程在销毁前存活的最大时间
        

     * @param unit the time unit for the {@code keepAliveTime} argument
     空闲时间的单位

     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     在任务被执行之前,保留任务的队列,当然了,必须是通过execute方法提交的任务。
     

     * @param threadFactory the factory to use when the executor
     *        creates a new thread
     executor创建出一个新线程使用的线程工厂。


     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
     任务队列满的时候,如何处理接收的任务

        
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue}
     *         or {@code threadFactory} or {@code handler} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

理解:
可以看出来,传递完参数后,其实并没有创建任何线程,也就是创建线程是一个懒惰的过程,只有提交任务时,才会创建线程。

2)提交任务到任务队列 // java.util.concurrent.ThreadPoolExecutor#execute

使用:

 public void accountDeleteExecute(Runnable command){
     accountDeleteExecutor.execute(command);
 }

源码分析:

   /**
     * Executes the given task sometime in the future.  The task
     * may execute in a new thread or in an existing pooled thread.  
     在未来某一时刻执行给定的任务,任务可能在一个新线程执行也可能在一个池子中已经存在的线程执行。

     *
     * If the task cannot be submitted for execution, either because this
     * executor has been shutdown or because its capacity has been reached,
     * the task is handled by the current {@link RejectedExecutionHandler}.
     提交的任务不会被执行的情况:
        1.executor被关闭
        2.容量达到上限,此时就会使用拒绝策略进行处理。     


     * @param command the task to execute
     * @throws RejectedExecutionException at discretion of
     *         {@code RejectedExecutionHandler}, if the task
     *         cannot be accepted for execution
     * @throws NullPointerException if {@code command} is null
     */
    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        /*
         * Proceed in 3 steps:
         *
         * 1. If fewer than corePoolSize threads are running, try to
         * start a new thread with the given command as its first
         * task.  The call to addWorker atomically checks runState and
         * workerCount, and so prevents false alarms that would add
         * threads when it shouldn't, by returning false.
         如果运行着的线程数小于核心数,会尝试new一个新的线程,拿command作为第一个任务。
         addWorker方法会自动检查运行状态和任务的数量,在不该添加线程时返回false

         *
         * 2. If a task can be successfully queued, then we still need
         * to double-check whether we should have added a thread
         * (because existing ones died since last checking) or that
         * the pool shut down since entry into this method. So we
         * recheck state and if necessary roll back the enqueuing if
         * stopped, or start a new thread if there are none.
         如果一个任务成功入队,我们依然需要去双重检测一下是否我们应该添加一个新的线程,
         因为有可能最后一次检查,可能线程死了,或者当我们进入方法执行时,线程池被关闭,
         所以我们重新检查是否需要出队如果线程池被关闭了,或者开启一个新的线程。


         *
         * 3. If we cannot queue task, then we try to add a new
         * thread.  If it fails, we know we are shut down or saturated
         * and so reject the task.
         如果我们不能入队,则我们尝试添加一个新的线程,失败的话,我们就知道现在线程池被关闭了
         或者饱和了,所以我们拒绝这个任务。

         */
        // 这个值由: wrkerCount和runState组成
        int c = ctl.get();
        
        // 看下worker的数量是否小于核心线程数量
        if (workerCountOf(c) < corePoolSize) {
            // 尝试添加一个worker,添加成功就直接返回return了
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        
        // 走到这里说明没添加新的线程,那么就把任务扔到任务队列中
        // 这里使用低x位去取得线程池运行状态
        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);
    }

3)任务队列中取任务执行

源码分析(新建Worker,并处理第一个任务)

 /**
     * Checks if a new worker can be added with respect to current
     * pool state and the given bound (either core or maximum). If so,
     * the worker count is adjusted accordingly, and, if possible, a
     * new worker is created and started, running firstTask as its
     * first task. This method returns false if the pool is stopped or
     * eligible to shut down. It also returns false if the thread
     * factory fails to create a thread when asked.  If the thread
     * creation fails, either due to the thread factory returning
     * null, or due to an exception (typically OutOfMemoryError in
     * Thread.start()), we roll back cleanly.
     *
     * @param firstTask the task the new thread should run first (or
     * null if none). Workers are created with an initial first task
     * (in method execute()) to bypass queuing when there are fewer
     * than corePoolSize threads (in which case we always start one),
     * or when the queue is full (in which case we must bypass queue).
     * Initially idle threads are usually created via
     * prestartCoreThread or to replace other dying workers.
     *
     * @param core if true use corePoolSize as bound, else
     * maximumPoolSize. (A boolean indicator is used here rather than a
     * value to ensure reads of fresh values after checking other pool
     * state).
     * @return true if successful
     */
    private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (int c = ctl.get();;) {
            // Check if queue empty only if necessary.
            if (runStateAtLeast(c, SHUTDOWN)
                && (runStateAtLeast(c, STOP)
                    || firstTask != null
                    || workQueue.isEmpty()))
                return false;

            for (;;) {
                if (workerCountOf(c)
                    >= ((core ? corePoolSize : maximumPoolSize) & COUNT_MASK))
                    return false;
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                c = ctl.get();  // Re-read ctl
                if (runStateAtLeast(c, SHUTDOWN))
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
        }

        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
            // new一个Worker,其实这就是一个Runnable,作为Worker的第一个任务
            w = new Worker(firstTask);
            // 这个是Worker里面使用线程工厂new的线程,但是还没启动
            final Thread t = w.thread;
            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 c = ctl.get();

                    if (isRunning(c) ||
                        (runStateLessThan(c, STOP) && firstTask == null)) {
                        if (t.getState() != Thread.State.NEW)
                            throw new IllegalThreadStateException();
                        // 新的Worker记录下
                        workers.add(w);
                        workerAdded = true;
                        int s = workers.size();
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                    }
                } finally {
                    mainLock.unlock();
                }
                if (workerAdded) { 
                    // Worker线程真正的启动
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }

源码分析(Worker不断地取任务并执行)

/**
     * Main worker run loop.  Repeatedly gets tasks from queue and
     * executes them, while coping with a number of issues:
     *
     * 1. We may start out with an initial task, in which case we
     * don't need to get the first one. Otherwise, as long as pool is
     * running, we get tasks from getTask. If it returns null then the
     * worker exits due to changed pool state or configuration
     * parameters.  Other exits result from exception throws in
     * external code, in which case completedAbruptly holds, which
     * usually leads processWorkerExit to replace this thread.
     *
     * 2. Before running any task, the lock is acquired to prevent
     * other pool interrupts while the task is executing, and then we
     * ensure that unless pool is stopping, this thread does not have
     * its interrupt set.
     *
     * 3. Each task run is preceded by a call to beforeExecute, which
     * might throw an exception, in which case we cause thread to die
     * (breaking loop with completedAbruptly true) without processing
     * the task.
     *
     * 4. Assuming beforeExecute completes normally, we run the task,
     * gathering any of its thrown exceptions to send to afterExecute.
     * We separately handle RuntimeException, Error (both of which the
     * specs guarantee that we trap) and arbitrary Throwables.
     * Because we cannot rethrow Throwables within Runnable.run, we
     * wrap them within Errors on the way out (to the thread's
     * UncaughtExceptionHandler).  Any thrown exception also
     * conservatively causes thread to die.
     *
     * 5. After task.run completes, we call afterExecute, which may
     * also throw an exception, which will also cause thread to
     * die. According to JLS Sec 14.20, this exception is the one that
     * will be in effect even if task.run throws.
     *
     * The net effect of the exception mechanics is that afterExecute
     * and the thread's UncaughtExceptionHandler have as accurate
     * information as we can provide about any problems encountered by
     * user code.
     *
     * @param w the worker
     */
    这个方法是在Worker的run方法中执行,所以就是不断出去任务执行
    final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        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);
                    try {
                        task.run();
                        afterExecute(task, null);
                    } catch (Throwable ex) {
                        afterExecute(task, ex);
                        throw ex;
                    }
                } finally {
                    task = null;
                    w.completedTasks++;
                    w.unlock();
                }
            }
            completedAbruptly = false;
        } finally {
            processWorkerExit(w, completedAbruptly);
        }
    }

4)关闭

使用:

    @Override
    public void shutdown(){
        if(accountDeleteExecutor != null){
            accountDeleteExecutor.shutdown();
        }
    }

线程池关闭源码分析

    /**
     * Initiates an orderly shutdown in which previously submitted
     * tasks are executed, but no new tasks will be accepted.
     * Invocation has no additional effect if already shut down.
     *
     * <p>This method does not wait for previously submitted tasks to
     * complete execution.  Use {@link #awaitTermination awaitTermination}
     * to do that.
     *
     * @throws SecurityException {@inheritDoc}
     */
    public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            checkShutdownAccess();
            advanceRunState(SHUTDOWN);
            // 调用线程的interrupt
            interruptIdleWorkers();
            onShutdown(); // hook for ScheduledThreadPoolExecutor
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
    }

二、拒绝策略 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值