线程池的核心线程会销毁吗?

今天跟别人讨论了线程池的核心线程会不会销毁的问题
先上代码

public static void main(String[] args) throws InterruptedException {
    ThreadPoolExecutor pool = new ThreadPoolExecutor(4,10,5, TimeUnit.SECONDS,new LinkedBlockingDeque<>(20));
    //pool.allowCoreThreadTimeOut(true);
    int a = 10;

    for (int i = 1; i <= a; i++) {
        int j = i;
        pool.submit(new Runnable() {
            @Override
            public void run() {
                if(j == 10){
                    throw new RuntimeException();
                }
                //获取线程名称
                Thread thread = Thread.currentThread();
                String name = thread.getName();
                //输出
                int activeCount = pool.getActiveCount();
                System.out.println("任务:"+j+"-----,线程名称:"+name+"-----活跃线程数:"+activeCount+"-----线程数"+pool.getPoolSize());
            }
        });
    }
    Thread.sleep(6000);
    System.out.println("线程数"+pool.getPoolSize()+"-----,活跃线程数"+pool.getActiveCount());
}

结果:活跃线程数为0,池内线程数量为核心线程数(这里要注意getPoolSize和getActiveCount不要混为一谈!!!线程不活跃了但是还是在池子里!!!只是空闲了,另外看评论区可能有一些同学会误解,这里是在线程池完全空闲时,用getPoolSize的数量与corePoolSize数量一致来说明线程池的确创建了4个核心线程池,而不是说getPoolSize就是核心线程数)如果对线程池原理不够理解,点这里
线程池的核心线程会销毁吗?_第1张图片

大家可能看到我注释了一行代码,那么就看看不注释掉的运行结果

public static void main(String[] args) throws InterruptedException {
    ThreadPoolExecutor pool = new ThreadPoolExecutor(4,10,5, TimeUnit.SECONDS,new LinkedBlockingDeque<>(20));
    pool.allowCoreThreadTimeOut(true);
    int a = 10;

    for (int i = 1; i <= a; i++) {
        int j = i;
        pool.submit(new Runnable() {
            @Override
            public void run() {
                if(j == 10){
                    throw new RuntimeException();
                }
                //获取线程名称
                Thread thread = Thread.currentThread();
                String name = thread.getName();
                //输出
                int activeCount = pool.getActiveCount();
                System.out.println("任务:"+j+"-----,线程名称:"+name+"-----活跃线程数:"+activeCount+"-----线程数"+pool.getPoolSize());
            }
        });
    }
    Thread.sleep(6000);//一定要大于KeepAliveTime的值
    System.out.println("线程数"+pool.getPoolSize()+"-----,活跃线程数"+pool.getActiveCount());
}

结果:核心线程被销毁了,线程数为0:

线程池的核心线程会销毁吗?_第2张图片
corePoolSize:返回核心线程数,类似于配置,不会随着核心线程被销毁而改变,所以我们用getPoolSize来进行验证


    /**
     * Core pool size is the minimum number of workers to keep alive
     * (and not allow to time out etc) unless allowCoreThreadTimeOut
     * is set, in which case the minimum is zero.
     */
    private volatile int corePoolSize;

allowCoreThreadTimeOut设置控制核心线程是否可以超时并终止的策略,如果在保活时间内没有任务到达,则在新任务到达时根据需要替换。当为 false 时,核心线程永远不会由于缺少传入任务而终止。如果为真,则适用于非核心线程的相同保活策略也适用于核心线程。为避免持续的线程替换,设置 true 时保持活动时间必须大于零。通常应该在主动使用池之前调用此方法。


    /**
     * If false (default), core threads stay alive even when idle.
     * If true, core threads use keepAliveTime to time out waiting
     * for work.
     */
    private volatile boolean allowCoreThreadTimeOut;

getPoolSize:返回线程池当前线程数


    /**
     * Returns the current number of threads in the pool.
     *
     * @return the number of threads
     */
    public int getPoolSize() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            // Remove rare and surprising possibility of
            // isTerminated() && getPoolSize() > 0
            return runStateAtLeast(ctl.get(), TIDYING) ? 0
                : workers.size();
        } finally {
            mainLock.unlock();
        }
    }

源码:直接看runWorker的processWorkerExit

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;
    } finally {
    //无论如何都会执行到这个方法
        processWorkerExit(w, completedAbruptly);
    }
}

看来重点在processWorkerExit方法

private void processWorkerExit(Worker w, boolean completedAbruptly) {
    if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
        decrementWorkerCount();

    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        completedTaskCount += w.completedTasks;
        workers.remove(w);
    } finally {
        mainLock.unlock();
    }

    tryTerminate();

    int c = ctl.get();
    if (runStateLessThan(c, STOP)) {
        if (!completedAbruptly) {
        //allowCoreThreadTimeOut 默认false 即 min默认为corePoolSize
            int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
            //如果min为0但是工作队列不为空,则至少要创建一个新的worker
            if (min == 0 && ! workQueue.isEmpty())
                min = 1;
            if (workerCountOf(c) >= min)
                return; // replacement not needed
        }
        addWorker(null, false);
    }
}

结论:当allowCoreThreadTimeOut手动设置为true或者执行的run方法抛出异常,核心线程都会被销毁,但是后者还是会创建新的线程称呼来,前者则销毁什么都不做,关键在于allowCoreThreadTimeOut为true则下面代码直接返回,不在执行addWorker方法

if (workerCountOf(c) >= min)
    return; // replacement not needed

你可能感兴趣的:(JAVA并发高级,java,开发语言,后端)