通过源码分析为什么不推荐使用Executors线程池

news2024/9/29 1:28:08

线程池是 Java 并发编程中不可缺少的一部分。JDK 提供了一个方便快捷的线程池工具类 Executors,提供了多种创建线程池的静态方法,但是在实际使用中,我们不建议直接使用 Executors 提供的线程池工具类。本篇博客将通过分析 Executors 源码,介绍为什么不推荐使用 Executors 线程池。

newCachedThreadPool

    /**
     * 创建一个线程池,根据需要创建新线程,但在以前构造的线程可用时重用它们。
     * 这些池通常会提高执行许多短期异步任务的程序的性能。对execute的调用将重用先前构造的线程(如果可用)。
     * 如果没有可用的线程,将创建一个新线程并将其添加到池中。60秒内未使用的线程将被终止并从缓存中删除。
     * 因此,空闲时间足够长的池不会消耗任何资源。
     * @return the newly created thread pool
     */
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

从源码中可以看出,newCachedThreadPool的核心线程为0,最大线程数为Integer.MAX_VALUE,队列为SynchronousQueue,该队列要求只有线程获取任务的话才能加入队列中。如果线程池的大小超过处理任务的线程,那么就会回收空闲线程。因为该线程池的最大线程数量为 Integer.MAX_VALUE,任务量过多时,可能会创建大量的线程,从而导致 OOM。

newFixedThreadPool(int nThreads)

    /**
     * 创建一个线程池,该线程池重用固定数量的线程,这些线程在共享无界队列上操作。
     * 在任何时候,最多nThreads线程将是活动的处理任务。
     * 如果在所有线程都处于活动状态时提交了额外的任务,它们将在队列中等待,直到有一个线程可用。
     * 任何线程在关闭之前的执行过程中由于失败而终止,如需要执行后续任务,将会有一个新的线程取代它的位置。
     * 在显式关闭池之前,池中的线程将一直存在。
     * @param nThreads the number of threads in the pool
     * @return the newly created thread pool
     * @throws IllegalArgumentException if {@code nThreads <= 0}
     */
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

从newFixedThreadPool源码可以看出,该方法会创建一个固定大小的线程池。核心线程数和最大线程数一致,当接受一个任务后就创建一个线程直至达到最大线程数。此时会将任务加入工作队列中工作队列采用的是无界的阻塞队列,支持先提交的先执行。因为LinkedBlockingQueue队列是无参构造,默认最大可存放请求数为 Integer.MAX_VALUE ,当任务量过多时,可能会导致大量任务堆积到队列中,从而导致 OOM。

newSingleThreadExecutor()


    /**
     * 创建一个Executor,该Executor使用单个工作线程对无界队列进行操作。
     * (但是请注意,如果这个线程在关闭之前的执行期间由于失败而终止,如果需要执行后续任务,
     * 将会有一个新的线程取代它的位置。)
     * 任务保证按顺序执行,并且在任何给定时间活动的任务不超过一个。与newFixedThreadPool(1)不同,
     * 返回的执行器保证不能重新配置以使用其他线程。
     * @return the newly created single-threaded Executor
     */
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

从newSingleThreadExecutor源码中可以看到核心线程数是1,最大线程数也是1,队列采用的是无界的LinkedBlockingQueue阻塞队列。如果核心线程异常的话,则创建一个线程去顶替核心线程(但始终保持单线程),因为队列是无参构造,默认最大可存放请求数为 Integer.MAX_VALUE ,当任务量过多时,可能会导致大量任务堆积到队列中,从而导致 OOM。

newScheduledThreadPool(int corePoolSize)

    /**
     * 创建一个线程池,该线程池可以安排命令在给定延迟后运行,或定期执行。
     * @param corePoolSize the number of threads to keep in the pool,
     * even if they are idle
     * @return a newly created scheduled thread pool
     * @throws IllegalArgumentException if {@code corePoolSize < 0}
     */
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
    //ScheduledThreadPoolExecutor源码
    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

newScheduledThreadPool线程池是支持定时任务的线程池,可以指定核心线程数,最大线程数为Interger.MAX_VALUE,内部使用的是:DelayedWorkQueue无界优先级阻塞队列。要求元素都实现 Delayed 接口。因为该线程池的最大线程数量为 Integer.MAX_VALUE,任务量过多时,可能会创建大量的线程,从而导致 OOM。

总结

Executors是JDK提供的一个线程池工具类,可以通过Executors提供的静态方法来创建不同类型的线程池。虽然Executors使用起来方便快捷,但是在实际应用中并不推荐直接使用,主要原因如下:

  1. 线程池参数的默认值不合理:Executors提供的默认线程池参数,在很多情况下并不是最优的选择。例如FixedThreadPool和SingleThreadPool中的队列大小都为Integer.MAX_VALUE,这会导致大量任务排队等待,从而触发OOM导致服务宕机。newCachedThreadPool和newScheduledThreadPool会创建一个可缓存线程池,没有固定的线程数限制,如果有新的任务需要执行,则会创建新的线程去执行任务。而当线程池空闲一段时间后,创建的线程将会被销毁。如果同时有大量请求到达,在新线程创建之前,可能会导致服务端过多的线程,从而造成系统资源的浪费和CPU负载过高。在实际应用中,我们往往需要根据实际情况来设置合理的线程数和队列大小。

  2. 线程池的创建方式不利于优化和扩展:Executors提供的线程池创建方式较为简单,不支持对线程池进行细粒度的配置和优化。如果需要根据具体需求进行调整,可能需要重新编写线程池实现代码,而这通常会涉及到复杂的多线程操作和同步控制。

  3. 线程池的抛弃策略处理不够友好:当线程池中的队列已满,无法再提交新任务时,线程池的默认抛弃策略是AbortPolicy,即直接抛出RejectedExecutionException异常。这样会导致服务直接崩溃,无法处理后续请求。而通过自定义抛弃策略,可以对任务进行缓存、持久化等操作,以便后续再次尝试执行。

因此,为了更好的控制线程池的行为、实现更细粒度的优化和扩展,并且避免由于线程池配置不合理或者抛弃策略不友好,造成服务宕机等问题,建议开发人员采用手动编写线程池方式,根据实际情况进行调整并实现线程池的自定义扩展功能。


自定义线程池参考文章:

SpringBoot + @Async 使用自定义线程池实现多线程任务处理

Spring异步注解@Async 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/671015.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【高性能计算】基于K均值的划分聚类实验

【高性能计算】基于K均值的划分聚类实验 实验目的实验内容实验步骤1、k均值聚类算法1.1 k均值聚类算法的基本思想1.2 k均值聚类算法的聚类过程1.3 k均值聚类算法的算法叙述 2、使用Python语言编写k均值聚类算法的源程序代码并分析其分类原理2.1 读取文件数据并进行可视化2.2 利…

推荐系统中的EE算法

人生中有很多选择问题&#xff0c;当每天中午吃饭的时候&#xff0c;需要选择吃饭的餐馆&#xff0c;那么就面临一个选择&#xff0c;是选择熟悉的好吃的餐馆呢&#xff0c;还是冒风险选择一个没有尝试过的餐馆呢。同样的&#xff0c;推荐系统处处也面临着这样的选择&#xff0…

操作系统 复习-计算题

一. 计算题&#xff08;共5题&#xff0c;100分&#xff09; 1.(计算题) 假设有4个进程需要在单CPU上运行&#xff0c;它们的执行时间如下表所示&#xff1a; 进程ID执行时间P18P25P32P44 现在我们需要按照抢占式优先级调度算法来安排这些进程的执行顺序。其中&#xff0c;进…

云原生之深入解析Kubernetes应用包管理器Helm的保姆级教程和实战

一、Helm 简介 ① 什么是 Helm&#xff1f; 我们可以将 Helm 看作 Kubernetes 下的 apt-get/yum&#xff0c;Helm 是 kubernetes 的包管理器&#xff0c;Helm 仓库里面只有配置清单文件&#xff0c;而没有镜像&#xff0c;镜像还是由镜像仓库来提供&#xff0c;比如 hub.dock…

【新星计划·2023】Linux内核、发行版讲解,它们有什么区别?

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 作者会持续更新网络知识和python基础知识&#xff0c;期待你的关注 目录 一、Linux内核版 二、Linux发行版 1、Debian 2、Slackware 3、Red Hat 4、Gentoo 三、内核版和发行版的区别 1、内核版 2、发行…

【Java高级语法】(十一)枚举类:还在因为使用了魔法数而被老大怼吗,一起来看看枚举器的作用吧!~

Java高级语法详解之枚举类 1️⃣ 概念2️⃣ 优势和缺点3️⃣ 使用&#x1f50d; Enum类的常用方法 4️⃣ 特征5️⃣ 应用场景&#x1f33e; 总结 1️⃣ 概念 Java枚举类&#xff08;Enumerator&#xff09;是在Java 5中引入的新特性&#xff0c;以提供一种更好的方式来表示固定…

TestOne自动化测试日志自动分类算法,帮助用户快速处理执行错误!

自动化测试的每次执行&#xff0c;都会产生大量的日志信息。特别是当执行发生错误&#xff0c;比如数据库异常、通讯异常等情况的时候&#xff0c;大量执行的自动化测试用例会报错。 实际上&#xff0c;很多错误的类型是比较类似的&#xff0c;但由于测试用例的数量很大&#x…

Goby 漏洞发布|泛微E-office协同办公系统 download.php 文件 filename 参数文件读取漏洞

漏洞名称&#xff1a;泛微E-office协同办公系统 download.php 文件 filename 参数文件读取漏洞 English Name&#xff1a;maxView Storage Manager dynamiccontent.properties.xhtml RCE CVSS core: 5.0 影响资产数&#xff1a;4971 漏洞描述&#xff1a; 泛微E-office协同…

餐饮点餐外卖小程序软件开发

餐饮点餐外卖小程序是一种基于微信平台的&#xff0c;提供在线点餐、外卖配送等服务的应用程序。以下是可能有助于餐饮点餐外卖小程序软件开发的功能&#xff1a; 商品展示&#xff1a;提供菜品分类、搜索、详情等功能&#xff0c;让用户可以方便快捷地查看商品信息。 …

研发效能平台的“双流”模型

本文摘于《软件研发效能权威指南》——第 9 章 核心观点 开发人员在多个“单点式”工具平台之间的来回切换是很耗费时间和精力的。“一站式”是指把研发各个环节的软件工程能力集成在一个统一的平台上&#xff0c;对新人友好&#xff0c;对老人提效。“一键式”是指让研发工程…

【流光溢彩】物联网入门 - ESP8266 + WS2812B 制作流光溢彩灯带

一、硬件准备 ESP8266 模块 x1WS2812B 灯带&#xff08;60/米&#xff0c;根据显示器四周长度买即可&#xff09; x1杜邦线 若干DC 电源 x1 二、软件准备 1. ESP8266 串口驱动 一般购买详情页都会有写&#xff0c;没有就找商家要一个。 一般是 CH340 或者 CP2102&#xff0c…

在 C4D 和 Redshift 中设置程序变形鸡尾酒动画

今天瑞云渲染小编给大家带来动画设计师 Victor V. 分享的 Pick Your Weapon 项目背后的工作流程&#xff0c;展示了 Cinema 4D 工作流程&#xff0c;并解释了动画是如何在 Redshift 中渲染的。 介绍 我是 Victor&#xff0c;我是居住在意大利的智利动画设计师&#xff0c;一年…

Xcode 14.3.1 (14E300c) 下载 - Apple 平台 IDE

Xcode 14.3.1 (14E300c) 下载 - Apple 平台 IDE Command Line Tools for Xcode 14, tvOS 16 & watchOS 9 Simulator Runtime 请访问原文链接&#xff1a;https://sysin.org/blog/apple-xcode-14/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页…

基于Confluent Kafka部署Kafka Connect集群,Kafka Connect集群加载debezium插件

基于Confluent Kafka部署Kafka Connect集群&#xff0c;Kafka Connect集群加载debezium插件 一、下载Confluent Kafka二、配置文件connect-distributed.properties三、启动脚本connect-distributed四、启动Kafka Connect集群五、加载debezium插件六、总结和延伸 一、下载Conflu…

leetcode39. 组合总和(回溯算法-java)

组合总和 leetcode39. 组合总和题目描述解题思路代码演示 回溯算法专题 leetcode39. 组合总和 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/combination-sum 题目描述 给你一个 无重复元素 的整数数组 candidates 和一…

浏览器跨域限制:为什么浏览器不能跨域发送Ajax请求?

&#x1f482; 个人网站:【海拥】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 目录 前言什么是跨域请求&am…

什么是虚拟展厅?教您快速打造一个3D元宇宙虚拟展厅

引言&#xff1a; 在如今的数字化时代&#xff0c;虚拟展厅和3D元宇宙成为了展示和推广产品、品牌以及创意的新兴方式。虚拟展厅为企业带来了无限的可能性&#xff0c;如何快速打造一个3D元宇宙虚拟展厅成了许多企业想了解的。 一&#xff0e;虚拟展厅的魅力 1.什么是虚拟展厅…

BUUCTF刷题十一道(07)

文章目录 [Zer0pts2020]Can you guess it?[CISCN2019 华北赛区 Day1 Web2]ikun[GWCTF 2019]枯燥的抽奖[WUSTCTF2020]CV Maker[NCTF2019]True XML cookbook[RCTF2015]EasySQL[CISCN2019 华北赛区 Day1 Web1]Dropbox[CISCN2019 华北赛区 Day1 Web5]CyberPunk[红明谷CTF 2021]wri…

防汛四级应急响应启动,尾矿库如何安全度过汛期?

国家防总办公室向上海、江苏、浙江、安徽、江西、河南、湖北、湖南、广西、重庆、四川、贵州、云南等省份防指下发通知&#xff0c;要求全面压实以地方行政首长负责制为核心的各项防汛责任&#xff0c;加强精准监测预报和会商研判&#xff0c;落实好“叫应”机制&#xff0c;确…

我把一句话需求交给AI,它竟然给我返回了……

&#x1f449;腾小云导读 也许你经历过这种情况&#xff1a;产品和设计同学用一句话就把需求说完了&#xff0c;你抓破脑袋做出来的版本又达不到他们的要求。不如尝试让 AI 承担痛苦&#xff0c;让它理解、拆解并实现一句话需求&#xff1f;本篇作者尝试提出一个自动配置可视化…