java线程池核心线程不被摧毁的原理及分析

 更新时间:2025年05月07日 11:18:04   作者:春风十里不及你  
这篇文章主要介绍了java线程池核心线程不被摧毁的原理及分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

为什么要用线程池?

  • 减少了创建和销毁线程的次数,每个工作线程都可以被重复利用
  • 可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因线程过多消耗内存,也避免了因线程过少,浪费系统资源

如何做到每个工作线程都可以被重复利用呢?

先看下线程池的工作原理:

原理如上图,线程池有七个核心参数

  • corePoolSize 线程池核心线程数
  • maximumPoolSize 线程池最大线程数量
  • keepAliveTime 空闲线程存活时间
  • unit 空闲线程存活时间单位
  • workQueue 工作队列
  • threadFactory 线程工厂
  • handler 拒绝策略

线程池之所以能做到重复利用,是因为线程池的核心线程不会被摧毁,执行完任务后会重复利用

线程池是如何保持核心线程不被摧毁呢?

首先看先线程池是如何处理任务的,如下图

下面我们看下核心部分源码:

  • 当有一个任务添加进来时,线程池会创建一个Worker,Worker是实现Runnable方法的,所以Worker执行时会调用run方法,run方法会接着调用runWoker方法
  • 主要看这一行代码,调用getTask方法获取任务并且执行 while (task != null || (task = getTask()) != null)
final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        w.firstTask = null;
        w.unlock(); // allow interrupts
        boolean completedAbruptly = true;
        try {
            // 主要看这一行代码,调用getTask方法获取任务并且执行
            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);
        }
    }
  • 看下getTask方法是如何实现的
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;

            if ((wc > maximumPoolSize || (timed && timedOut))
                && (wc > 1 || workQueue.isEmpty())) {
                if (compareAndDecrementWorkerCount(c))
                    return null;
                continue;
            }

            try {
                Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take();
                if (r != null)
                    return r;
                timedOut = true;
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }
  • 主要看这几行代码

  • getTask方法通过调用任务队列的take方法,不断的获取线程

  • 如果任务队列里面数量为0,则会一直阻塞,一直等到有任务加入,从而保证了核心线程不被摧毁

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java三种求水仙花数的方法

    Java三种求水仙花数的方法

    本篇文章通过求水仙花数的实例来让大家对JAVA求数的概念和方法有更深入的理解和应用,学习参考下吧。
    2018-02-02
  • SpringMVC异步处理的 5 种方式示例详解

    SpringMVC异步处理的 5 种方式示例详解

    这篇文章主要介绍了SpringMVC异步处理的 5 种方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • UniApp + SpringBoot 实现支付宝支付和退款功能

    UniApp + SpringBoot 实现支付宝支付和退款功能

    这篇文章主要介绍了UniApp + SpringBoot 实现支付宝支付和退款功能,基本的 SpringBoot 的脚手架,可以去IDEA 自带的快速生成脚手架插件,本文通过实例代码给大家介绍的非常详细,需要的朋友参考下吧
    2022-06-06
  • SpringBoot使用Redis清除所有缓存实现方式

    SpringBoot使用Redis清除所有缓存实现方式

    文章介绍通过遍历删除Redis所有key的方法,推荐使用RedisTemplate的delete方法而非StringRedisTemplate,需确保缓存操作统一使用同类型模板,避免类型不匹配问题
    2025-08-08
  • Java的Tomcat和Servlet的运行原理详解

    Java的Tomcat和Servlet的运行原理详解

    这篇文章主要为大家详细介绍了Java的Tomcat和Servlet,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • 详解Java 自动装箱与自动拆箱

    详解Java 自动装箱与自动拆箱

    这篇文章主要介绍了Java 自动装箱与自动拆箱的相关资料,帮助大家更好的理解和学习Java,感兴趣的朋友可以了解下
    2020-09-09
  • Java实现AWT四大事件的详细过程

    Java实现AWT四大事件的详细过程

    AWT的事件处理是一种委派式事件处理方式:普通组件(事件源)将整个事件处理委托给特定的对象(事件监听器);当该事件源发生指定的事件时,就通知所委托的事件监听器,由事件监听器来处理这个事件
    2022-04-04
  • mac下idea启动web项目报错java.net.SocketException:socket closed问题

    mac下idea启动web项目报错java.net.SocketException:socket closed

    本文主要介绍了作者在项目启动时遇到的一个问题——无法打开调试端口,经过一系列排查和尝试,最终发现是由于权限问题导致的,作者还分享了如何修改文件权限的方法,并提醒大家不要随意kill掉占用端口的进程
    2024-12-12
  • 浅谈Java数值类型的转换与强制转换

    浅谈Java数值类型的转换与强制转换

    这篇文章主要介绍了Java数值类型的转换与强制转换,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • springboot jdbctemplate如何实现多数据源

    springboot jdbctemplate如何实现多数据源

    这篇文章主要介绍了springboot jdbctemplate如何实现多数据源问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07

最新评论