线程池——参数、状态、拒绝策略、execute()相关源码浅析

本文深入探讨了Java线程池的核心参数,包括核心线程数、最大线程数、存活时间等,并介绍了四种不同的拒绝策略。此外,文章还剖析了线程池的内部实现,特别是`execute()`方法的工作流程,以及`addWorker()`和`runWorker()`在任务调度中的角色。通过对源码的解析,读者可以更好地理解线程池的运行机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线程池

线程池参数

Creates a new ThreadPoolExecutor with the given initial parameters.
Params:
corePoolSize – the number of threads to keep in the pool, even if they are idle, unless allowCoreThreadTimeOut is set
maximumPoolSize – the maximum number of threads to allow in the pool
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.
unit – the time unit for the keepAliveTime argument
workQueue – the queue to use for holding tasks before they are executed. This queue will hold only the Runnable tasks submitted by the execute method.
threadFactory – the factory to use when the executor creates a new thread
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: corePoolSize < 0 keepAliveTime < 0 maximumPoolSize <= 0 maximumPoolSize < corePoolSize
NullPointerException – if workQueue or threadFactory or handler is null

  1. corePoolSize:线程池中永远不终止的线程,几遍线程内没有任务
  2. maximumPoolSize:线程池中的最大线程数量
  3. keepAliveTime :当线程数大于核心线程数时,多余的空闲线程多久终止
  4. unit :keepAliveTime 的单位
  5. workQueue :存放执行前的任务,只会存放通过execute方法提交的runnable任务
  6. threadFactory :线程工厂,用于创建新的线程
  7. handler :当queue满了的时候的处理器,有四种RejectedExecutionHandler的子类对应着四种拒绝策略

四种拒绝策略

  1. AbortPolicy抛异常(默认策略)

    public static class AbortPolicy implements RejectedExecutionHandler {
        /**
         * Creates an {@code AbortPolicy}.
         */
        public AbortPolicy() { }
    
        /**
         * Always throws RejectedExecutionException.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         * @throws RejectedExecutionException always
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }
    
  2. DiscardPolicy,直接无视

    /**
     * Does nothing, which has the effect of discarding task r.
     */
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    }
    
  3. DiscardOldestPolicy,扔掉最早的任务,执行新任务

    /**
     * Obtains and ignores the next task that the executor
     * would otherwise execute, if one is immediately available,
     * and then retries execution of task r, unless the executor
     * is shut down, in which case task r is instead discarded.
     */
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            e.getQueue().poll();
            e.execute(r);
        }
    }
    
  4. CallerRunsPolicy,使用当前线程执行任务

    /**
     * Executes task r in the caller's thread, unless the executor
     * has been shut down, in which case the task is discarded.
     */
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            r.run();
        }
    }
    

线程池的五种状态(待补充)

image

  1. running
  2. shutdown
  3. stop
  4. tidying
  5. terminated

线程池execute相关方法源码浅析

在这里插入图片描述

execute()——添加任务

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.
     *
     * 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.
     */
    int c = ctl.get();
    // 线程数 < 核心线程数
    if (workerCountOf(c) < corePoolSize) { 
        if (addWorker(command, true)) // 添加新的核心线程
            return;
        c = ctl.get(); // 可能由多线程同时执行execute()方法,其他线程率先创建了足够的核心线程,那么后续按照核心线程已满执行
    }
    // 核心线程已足够
    if (isRunning(c) && workQueue.offer(command)) { // 线程池还在running状态,且队列不满(阻塞队列的呃offer()方法会在队列满时返回false)
        int recheck = ctl.get();
        if (! isRunning(recheck) && remove(command))
            reject(command);
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
    }
    else if (!addWorker(command, false)) // 队列满会尝试添加新线程,直至超过maximumPoolSize
        reject(command); // 执行对应的拒绝策略(默认为抛异常)
}

addWorker()——worker初始化(可以简单理解为线程初始化?)

private boolean addWorker(Runnable firstTask, boolean core) { // 参数:firstTask:要执行的Runnable任务, core是否为核心线程
    retry:
    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c); // 线程池状态

        // Check if queue empty only if necessary.
        if (rs >= SHUTDOWN && // 非 running && (不是shutdown || 任务 != null || queue为空)
            ! (rs == SHUTDOWN &&
               firstTask == null &&
               ! workQueue.isEmpty()))
            return false;

        for (;;) {
            int wc = workerCountOf(c); // 线程数
            if (wc >= CAPACITY || // 是否超过设定上限
                wc >= (core ? corePoolSize : maximumPoolSize))
                return false;
            if (compareAndIncrementWorkerCount(c)) // CAS增加线程个数,这里改变的是字段ctl
                break retry;
            c = ctl.get();  // Re-read ctl
            if (runStateOf(c) != rs)
                continue retry;
            // else CAS failed due to workerCount change; retry inner loop
        }
    }
	
    // CAS成功
    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) // 更新(似乎不太重要,只是个供我们get的参数)
                        largestPoolSize = s;
                    workerAdded = true;
                }
            } finally {
                mainLock.unlock(); // 解锁
            }
            if (workerAdded) {
                t.start(); // runWorker()方法,其中会执行初始任务,并继续从queue获取任务
                workerStarted = true;
            }
        }
    } finally {
        if (! workerStarted)
            addWorkerFailed(w);
    }
    return workerStarted;
}
// worker
Worker(Runnable firstTask) {
    setState(-1); // inhibit interrupts until runWorker
    this.firstTask = firstTask;
    this.thread = getThreadFactory().newThread(this); //通过线程池参数之一的threadFactory创建线程
}

// workers
private final HashSet<Worker> workers = new HashSet<Worker>();

runWorker()——每个线程时如何执行queue里的任务的

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);
                Throwable thrown = null;
                try {
                    task.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;
                w.completedTasks++;
                w.unlock();
            }
        }
        completedAbruptly = false; // 任务为null,且queue也没有拿到任务
    } finally {
        processWorkerExit(w, completedAbruptly); // 
    }
}

getTask()——keepAliveTime参数时如何运作的

private Runnable getTask() {
    boolean timedOut = false; // Did the last poll() time out?

    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);

        // Check if queue empty only if necessary.
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
            decrementWorkerCount();
            return null;
        }

        int wc = workerCountOf(c);

        // Are workers subject to culling?
        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; // core线程是否会过期 || 当前线程数 > corePoolSize,那么需要对corePoolSize以外的线程如果在keepAliveTime的时间内没有拿到任务,那么就要销毁线程 // 所以time表示的是是否要执行过期策略

        if ((wc > maximumPoolSize || (timed && timedOut)) // 给超时的空闲线程第二次机会
            && (wc > 1 || workQueue.isEmpty())) {
            if (compareAndDecrementWorkerCount(c))
                return null;
            continue;
        }

        try {
            Runnable r = timed ? // 是否执行过期策略?
                workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : // 过期:keepAliveTime时间内拿不到就设置timedOut = true;会在上面的代码中进行二次拯救,如果届时queue里还是没有任务,worker就被销毁
                workQueue.take(); // 不过期:阻塞直至拿到
            if (r != null)
                return r;
            timedOut = true;
        } catch (InterruptedException retry) {
            timedOut = false;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值