2024-08-04  阅读(1)
版权声明:本文为博主付费文章,严禁任何形式的转载和摘抄,维权必究。 本文链接:https://www.skjava.com/mianshi/baodian/detail/1696344715

回答

ThreadPoolExecutor 使用 corePoolSizemaximumPoolSize 控制核心线程数和最大线程数。初始时,线程池会创建核心线程数(corePoolSize)的线程来处理任务。当任务被提交到线程池后,线程池会首先尝试使用空闲的核心线程执行任务,如果没有空闲的核心线程,则任务会被放入任务队列(workQueue)。工作线程会从任务队列中获取任务执行,从而避免频繁创建和销毁线程。

那线程是如何实现复用的呢?在 ThreadPoolExecutor#runWorker() 方法中,工作线程会不断地从任务队列(workQueue)中获取任务,当一个线程执行完任务后,线程并不会直接退出,而是采用死循环的方式不断从任务队列中获取新的任务执行,只要任务队列中有任务,那么该线程就会一直执行下去。同时,调用它的方式并不是通过 Thread#start() 的方式,而是直接调用它的 run() ,这样把 run() 方法当做普通方法去调用执行业务逻辑,而不是通过调用 Thread#start() 去创建新的线程,从而实现线程复用。

扩展

我们直接看源码吧。

调用 execute() 方法 :

   public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        int c = ctl.get();
        if (workerCountOf(c) < corePoolSize) {
            // 小于  corePoolSize
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        if (isRunning(c) && workQueue.offer(command)) {
            // 大于 corePoolSize  且加入任务队列成功
            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(),那 addWorker() 的作用是什么呢?它的作用是在线程池中创建一个线程并执行第一个参数传入的任务,它的第二个参数是 boolean,用于判断校验值是使用 corePoolSize 还是 maxPoolSize。该方法我们只需要关注后面一段:

    private boolean addWorker(Runnable firstTask, boolean core) {
        // 省略代码

        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
            //将 firstTask 包装成一个 Worker
            w = new Worker(firstTask);
            final Thread t = w.thread;
            if (t != null) {
                // 省略代码
                if (workerAdded) {
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }