千家信息网

java的线程池原理是什么

发表于:2025-12-01 作者:千家信息网编辑
千家信息网最后更新 2025年12月01日,这篇文章将为大家详细讲解有关java的线程池原理是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。在之前已经使用过线程池了。在使用中,基本上就是初始
千家信息网最后更新 2025年12月01日java的线程池原理是什么

这篇文章将为大家详细讲解有关java的线程池原理是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

在之前已经使用过线程池了。在使用中,基本上就是初始化好线程池的实例之后,把任务丢进去,等待调度执行就可以了。使用起来非常简单方便。

new Thread弊端

  • 每次new Thread新建对象,性能差

  • 线程缺乏统一管理,可能无限制的新建线程,相互竞争,有可能占用过多系统资源导致死机或者OOM

  • 缺少更多功能,如更多执行、定期执行、线程中断

线程池的好处

  • 重用存在的线程,减少对象创建、消亡的开销,性能好

  • 可以有效控制最大并发线程数,提高系统资源利用率,同时可以避免过多资源竞争,避免阻塞

  • 提供定时执行、定期执行、单线程、并发数控制等高级功能

ThreadPoolExecutor

参数:

  • corePoolSize:核心线程数量。建议和cpu的核心数差不多,当有任务提交,检测当前线程池内的线程数小于corePoolSize的话,新建线程执行任务,而不会开始复用,会新建,直到达到corePoolSize。线程池内的线程数大于等于corePoolSize时,将任务放入workQueue等待。

  • maximumPoolSize:允许线程池内最大线程数。当队列满了之后,如果线程池内的线程数小于maximumPoolSize则新建线程,如果大于等于执行拒绝策略。
    如果maximumPoolSize是30,corePoolSize是10,当队列满了后只能再开20个线程。

  • workQueue:阻塞队列,存储等待执行的任务,很重要,会对线程池运行过程产生重大影响

  • keepAliveTime:线程没有任务执行时最多保持多久时间终止。线程池维护线程所允许的空闲时间。当线程池中的线程数量大于CorePoolSize时,如果这是没有新的任务提交,线程会等待,直到时间超过keepAliveTime才销毁。

  • unit:keepAliveTime的时间单位

  • threadFactory:线程工厂,用来创建线程,会有一个默认的工厂来创建线程。使用默认的工厂创建线程时,线程拥有相同的优先级,并且是非守护的线程,同时也设置了线程的名称。

  • rejectHandle:当拒绝处理任务时的策略。如果workQueue阻塞队列满了,并且没有空闲的线程时,这时还继续提交任务,我们就需要一种策略来处理这个任务。线程池总共提供了四种策略:

    1. 直接抛出异常,默认策略

    2. 用调用者所在的线程执行任务

    3. 丢弃队列中最靠前的任务,并执行当前任务

    4. 直接丢弃这个任务

如果运行的线程数小于CorePoolSize时,直接创建新线程创建任务,即使线程池中的其他线程是空闲的。

如果线程池中的线程数量大于等于CorePoolSize且小于maximumPoolSize时,则只有当wokQueue满时才创建新的线程去处理任务。

如果我们设置CorePoolSize与maximumPoolSize相等,那么创建的线程池大小是固定的,这时如果有新任务提交且workQueue还没满,就把请求放入workQueue中,等待空闲线程从workQueue中取任务进行处理。

如果运行的线程数量大于maximumPoolSize时,这时如果workQueue满,那么会通过一个拒绝策略参数来指定策略处理任务。

如果我们想降低系统资源的消耗,包括CPU的使用率、操作系统资源的消耗,可以设置一个较大的workQueue容量和较小的CorePoolSize容量,这样会降低线程处理的吞吐量。如果我们提交的任务经常发生阻塞,我们可以设置maximumPoolSize来设置线程池容量。如果我们队列容量较小,通常需要把maximumPoolSize设置大一些,这样CPU使用率会高一些。但是如果线程池容量设置过大,在提交人物数量过多的情况下,并发量会增加,那么线程间资源调度就是一个需要考虑的问题,反而会降低处理的吞吐量。

线程池状态

当我们初始化一个线程池之后,通常有上面几种状态。

running:可以接受新提交的任务,也能处理阻塞队列中的任务。

shutdown:关闭状态,当一个线程池实例处于shutdown状态时,不能再接收新提交的任务,但却可以继续处理阻塞队列中已经保存的任务。

stop:也不能接收新的任务,也不处理队列中的任务。会中断正在处理的线程任务。

tidying:所有任务都已经终止了,没有活动中的线程。当线程池进行该状态时候,会执行钩子方法terminated() 。

ThreadPoolExecutor中的方法

  1. execute():提交任务,交给线程池执行

  2. submit():提交任务,能够返回执行结果 相当于execute+Future

  3. shutdown():关闭线程池,等待任务都执行完

  4. shutdownNow():关闭线程池,不等待任务执行完

  5. getTaskCount():线程池已执行和未执行的任务总数

  6. getCompletedTaskCount():已完成的任务数量

  7. getPoolSize():线程池当前的线程数量

  8. getActiveCount():当前线程池中正在执行任务的线程数量

Executors框架接口

  • Executors.newCachedThreadPool:创建一个可缓存的线程池,如果线程池的长度超过了线程的需要,可以灵活回收空闲线程,如果没有回收的,可以新建线程

  • Executors.newFixedThreadPool:创建一个定长的线程池,可以控制线程的最大并发数,超出的线程会在队列中等待

  • Executors.newScheduledThreadPool:也是创建一个定长的线程池。支持定时以及周期性的任务执行。

  • Executors.newSingleThreadExecutor:创建一个单线程的线程池,会用唯一的工作线程来执行任务。保证所有任务按照指定顺序去执行(先入先出等)。

Executors.newCachedThreadPool示例代码:

@Slf4jpublic class ThreadPoolExample1 {    public static void main(String[] args) {        ExecutorService executorService = Executors.newCachedThreadPool();        for (int i = 0; i< 10; i++){            final int index = i;            executorService.execute(new Runnable() {                @Override                public void run() {                    log.info("task:{}", index);                }            });        }        //一定要关闭线程池,否则程序不结束        executorService.shutdown();    }}

Executors.newSingleThreadExecutor示例代码:

@Slf4jpublic class ThreadPoolExample3 {    public static void main(String[] args) {        ExecutorService executorService = Executors.newSingleThreadExecutor();        for (int i = 0; i< 10; i++){            final int index = i;            executorService.execute(new Runnable() {                @Override                public void run() {                    log.info("task:{}", index);                }            });        }        //一定要关闭线程池,否则程序不结束        executorService.shutdown();    }}

输出结果:

17:08:16.870 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:017:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:117:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:217:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:317:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:417:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:517:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:617:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:717:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:817:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:9

相当于单线程按顺序执行。

Executors.newScheduledThreadPool代码示例:

@Slf4jpublic class ThreadPoolExample4 {    public static void main(String[] args) {        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {            @Override            public void run() {                log.warn("schedule run");            }        },1, 3, TimeUnit.SECONDS);        //这里不需要关闭线程池        //scheduledExecutorService.shutdown();    }}

上面目的是:延迟1秒后,每个三秒执行一次任务,由于这个任务时不定的执行,因此这里不应该关闭线程池。如果需要关闭线程池的话,可以设置一个触发条件来关闭。类似于Timer类:

@Slf4jpublic class ThreadPoolExample4 {    public static void main(String[] args) {        Timer timer = new Timer();        timer.schedule(new TimerTask() {            @Override            public void run() {                log.warn("timer run");            }        }, new Date(), 5*1000);    }}

线程池合理配置

  • CPU密集型任务,就需要尽量压榨CPU,参考值可以设置为NCPU+1

  • 如果是IO密集型任务,参考值可以设置为2*NCPU

我们只用线程池主要是为了重用存在的线程,减少对象创建消亡,能有效控制最大线程并发数,可以避免过多的资源竞争和阻塞,也可以定时执行单线程与控制线程的执行性能比较好。 这不代表线程池应该随时随地用,一定要根据自己的实际场景来分析使用参数配置

关于java的线程池原理是什么就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

线程 任务 处理 队列 数量 策略 资源 阻塞 容量 状态 空闲 控制 最大 时间 更多 系统 过多 池内 代码 参数 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 手机待机完后提示连接不上服务器 奇虎360网络安全运维 关于网络安全的热点新闻 网络安全与执法大队队徽 石嘴山软件开发培训 华硕服务器主板卡b2后重启 贝腾创业总动员服务器地址 常州OA软件开发招聘网 计算机网络技术的重要点 软件开发企业运行模式 四川视觉引导点胶软件开发 江西软件开发咨询报价 erp数据库挂了怎么解决 郑州网络安全科技馆如何预约 网络安全等级保护政策是什么 中投期货服务器快吗 信息化网络安全岗位职责 用友软件数据库用清理吗 战术小队有哪些好玩的服务器 宝鸡市金台区网络安全宣誓仪式 天河正规物联网软件开发 网络安全的应用有哪些 网络安全发展规划 中标 DHCP服务器的主要配置文件 软件远程连接数据库 安全性 石油软件开发公司有哪些 mysql数据库主主热备 架cs服务器 dm8 数据库 北京卓晟互联网络技术有限公司
0