高薪程序员必修课-Java中为什么不建议使用Executors来创建线程池?

目录

前言

原因分析

1. newFixedThreadPool 和 newSingleThreadExecutor

示例:

2. newCachedThreadPool

示例:

建议的替代方法

示例:

解释:

总结


前言

        在Java中,Executors 类提供了几个工厂方法来创建不同类型的线程池,例如 newFixedThreadPoolnewCachedThreadPoolnewSingleThreadExecutor。虽然这些方法方便使用,但它们在某些情况下可能会带来潜在的问题,因此不建议在生产环境中直接使用 Executors 来创建线程池。下面从原理角度详细讲解原因,并提供相应的示例。

原因分析

1. newFixedThreadPoolnewSingleThreadExecutor

原理:这两个方法使用无界队列 LinkedBlockingQueue 作为任务队列。

问题:无界队列意味着队列可以无限增长。如果任务提交速度快于任务处理速度,队列中的任务会不断增加,可能导致内存耗尽(OOM)。

示例:
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < Integer.MAX_VALUE; i++) {executor.submit(() -> {try {Thread.sleep(1000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}});
}

在这个示例中,如果任务提交速度非常快,任务会无限制地排队,最终导致内存耗尽。

2. newCachedThreadPool

原理:该方法使用 SynchronousQueue 作为任务队列,并且线程池的最大线程数是 Integer.MAX_VALUE

问题SynchronousQueue 不存储任务,每个插入操作必须等待相应的移除操作。如果任务提交速度快于任务处理速度,会创建大量线程,可能导致系统资源耗尽(如CPU、内存等)。

示例:
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < Integer.MAX_VALUE; i++) {executor.submit(() -> {try {Thread.sleep(1000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}});
}

在这个示例中,如果任务提交速度非常快,会创建大量线程,最终导致系统资源耗尽。

建议的替代方法

为了更好地控制线程池的行为,建议使用 ThreadPoolExecutor 构造函数来创建线程池。这样可以更明确地指定线程池的参数,如核心线程数、最大线程数、任务队列类型和拒绝策略。

示例:
import java.util.concurrent.*;public class CustomThreadPoolExample {public static void main(String[] args) {// 创建一个具有自定义参数的线程池ThreadPoolExecutor executor = new ThreadPoolExecutor(10,                        // 核心线程数20,                        // 最大线程数60L,                       // 非核心线程的空闲时间TimeUnit.SECONDS,          // 空闲时间的单位new ArrayBlockingQueue<>(100),  // 有界任务队列new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略);for (int i = 0; i < 200; i++) {executor.submit(() -> {try {Thread.sleep(1000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}System.out.println(Thread.currentThread().getName() + " completed task");});}executor.shutdown();}
}
解释:
  1. 核心线程数和最大线程数

    • 核心线程数设置为10,最大线程数设置为20。
    • 线程池在初始时创建10个核心线程,任务提交超过10个时,会创建最多10个额外的线程(最大线程数-核心线程数)。
  2. 非核心线程的空闲时间

    • 非核心线程空闲时间设置为60秒,超过这个时间未处理任务的非核心线程将被终止。
  3. 有界任务队列

    • 使用 ArrayBlockingQueue,容量为100。这限制了任务队列的大小,避免无限增长导致内存耗尽。
  4. 拒绝策略

    • 使用 CallerRunsPolicy 作为拒绝策略。当任务队列已满且所有线程都在运行时,拒绝策略将任务返回给调用者线程执行,避免任务丢失。

总结

不建议使用 Executors 创建线程池的原因主要是它隐藏了线程池的具体实现,容易导致以下问题:

  1. 无界队列导致内存耗尽newFixedThreadPoolnewSingleThreadExecutor 使用无界队列,可能导致内存耗尽。
  2. 线程无限增长导致资源耗尽newCachedThreadPool 使用 SynchronousQueue 和无限制的最大线程数,可能导致系统资源耗尽。

使用 ThreadPoolExecutor 构造函数可以更精细地控制线程池的参数,从而避免这些潜在问题。

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

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

相关文章

RAG开源项目Qanything源码阅读3-在线推理

原文&#xff1a;前沿重器[47] | RAG开源项目Qanything源码阅读3-在线推理 项目&#xff1a;https://github.com/netease-youdao/QAnything 第一篇&#xff1a;RAG开源项目Qanything源码阅读1-概述服务 第二篇&#xff1a;RAG开源项目Qanything源码阅读2-离线文件处理 0&#x…

Pytest+Allure+Yaml+PyMsql+Jenkins+Gitlab接口自动化(五)Jenkins配置

一、背景 Jenkins&#xff08;本地宿主机搭建&#xff09; 拉取GitLab(服务器)代码到在Jenkins工作空间本地运行并生成Allure测试报告 二、框架改动点 框架主运行程序需要先注释掉运行代码&#xff08;可不改&#xff0c;如果运行报allure找不到就直接注释掉&#xff09; …

中英双语介绍美国的州:路易斯安那州(Louisiana)

中文版 路易斯安那州简介 路易斯安那州位于美国南部&#xff0c;以其丰富的历史文化、多样的自然景观和独特的音乐和美食传统而闻名。以下是对路易斯安那州的详细介绍&#xff0c;包括其地理位置、人口、经济、教育、文化和主要城市。 地理位置 路易斯安那州东临密西西比州…

鸿蒙应用开发-时间屏幕

点击下载源码&#xff1a; https://download.csdn.net/download/liuhaikang/89509449 做一个时间屏幕&#xff0c;可以点击切换白色和黑色&#xff0c;有渐变效果&#xff0c;使用到了鸿蒙的动画效果。 在这个设计中&#xff0c;我们首先引入了通用能力包&#xff0c;以实现功…

Kubernetes 离线安装的坑我采了

Kubernetes 离线安装的坑我采了 一、Error from server: Get "https://xx.xx.xx.xx:10250/containerLogs/kube-system/calico-node-8dnvs/calico-node": tls: failed to verify certificate: x509: certificate signed by unknown authority二、calico 或 pod 启动正…

cesium公交车轨迹漫游

个人博客&#xff1a;CSDN 博客-满分观察网友 z 演示地址&#xff1a;哔哩哔哩-满分观察网友 z 这是一个用 Cesium.js 做的公交车轨迹漫游&#xff0c;实现的功能有加载站点和道路轨迹点数据、监听车辆的实时位置、车辆控制器。滚动屏等等。 文章目录 1. 地图初始化2. 数据渲…

【高中数学/基本不等式】已知:x,y均为正实数,且xy+2x+y=4 求:x+y的最小值?

【问题】 已知&#xff1a;x,y均为正实数&#xff0c;且xy2xy4 求&#xff1a;xy的最小值&#xff1f; 【来源】 https://www.ixigua.com/7147585275823292942?logTagf25494de7fce23a3a3d0 【解答】 解&#xff1a; 由xy2xy4 两边加二得 xy2xy24 2 分解因式得 (x1)(…

0090__【Git系列】merge和rebase的区别

【Git系列】merge和rebase的区别_rebase和merge的区别-CSDN博客 git中rebase和merge的区别是什么-git-PHP中文网 https://blog.51cto.com/qzcsbj/9444199

从零搭建教育管理系统:Java + Vue.js 教学-02

第三步:创建实体类和 Mapper 接口 现在我们已经设计好了数据库表,接下来使用 MyBatis-Plus 将这些表映射到 Java 对象,以便在代码中轻松地进行操作。 1. 创建实体类 在 src/main/java/<your_package>/entity 目录下 (如果没有该目录,请手动创建),创建与数据库表对应…

MyBatis(20)MyBatis 事务管理如何实现

MyBatis 的事务管理是通过底层 JDBC 连接的事务管理机制来实现的。事务管理对于任何涉及多个数据库操作的应用程序来说都是至关重要的&#xff0c;它确保数据的一致性和完整性。在 MyBatis 中&#xff0c;事务管理可以通过 SQL 会话&#xff08;SqlSession&#xff09;来实现。…

【WEB前端2024】3D智体编程:乔布斯3D纪念馆-第53课-语音指令跳舞

【WEB前端2024】3D智体编程&#xff1a;乔布斯3D纪念馆-第53课-语音指令跳舞 使用dtns.network德塔世界&#xff08;开源的智体世界引擎&#xff09;&#xff0c;策划和设计《乔布斯超大型的开源3D纪念馆》的系列教程。dtns.network是一款主要由JavaScript编写的智体世界引擎&…

可信计算的完整专用名词列表

可信计算的完整专用名词列表 Trusted Computing - 可信计算Trusted Platform Module (TPM) - 可信平台模块Hardware Root of Trust - 硬件根信任Secure Boot - 安全启动Remote Attestation - 远程证明Integrity Measurement - 完整性度量Measurement Log - 度量日志Attestatio…

Android 图像效果的奥秘

在当今数字化时代&#xff0c;图像已经成为人们生活和工作中不可或缺的一部分。而在 Android 系统中&#xff0c;图像效果的应用更是丰富多彩&#xff0c;为用户带来了更加出色的视觉体验。本文将深入探讨 Android 图像效果的原理、实现方法以及应用场景&#xff0c;帮助读者更…

面试题springboot面试

文章目录 Spring的依赖注入构造器注入stetter注入属性注入 springboot的优势第一开箱即用约定大于配置内嵌tomcat服务器 javaweb的三大组件springboot的自动配置原理SpringIoc的实现机制springmvcspring如何简化开发 Spring的依赖注入 构造器注入 stetter注入 属性注入 使用…

按位异或^

在 Python 中&#xff0c;a ^ b 表示按位异或运算符。按位异或运算符对整数的每一位进行运算&#xff0c;如果对应位上的两个二进制数字不同&#xff0c;则结果为 1&#xff0c;否则为 0。 示例 a 5 # 二进制: 0101 b 3 # 二进制: 0011result a ^ b print(result) # 输…

私域流量:塑造企业数字营销的未来

在当今数字化的时代&#xff0c;流量成为了商业世界中的新货币&#xff0c;而“私域流量”更是其中的黄金。但“私域流量”究竟是什么&#xff1f;它如何成为企业数字化转型和营销策略中不可或缺的一部分&#xff1f;本文将探讨私域流量的概念&#xff0c;并通过案例分析其运营…

前端进阶:Vue.js

目录 框架&#xff1a; 助解&#xff1a; 框架&#xff1a; VUE 什么是Vue.js? Vue.js优点 Vue安装 方式一&#xff1a;直接用<script>引入 方式二&#xff1a;命令行工具 第一个Vue程序 代码 代码解释&#xff1a; 运行 Vue指令 v-text v-html v-tex…

Mysql和ES使用汇总

一、mysql和ES在业务上的配合使用 一般使用时使用ES 中存储全文检索的关键字与获取的商品详情的id&#xff0c;通过ES查询获取查询商品的列表中展示的数据&#xff0c;通过展示id 操作去获取展示商品的所有信息。mysql根据id去查询数据库数据是很快的&#xff1b; 为什么ES一般…

JavaScript如何声明json对象

在JavaScript中&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;对象实际上是以JavaScript对象的形式表示的。JSON是一种轻量级的数据交换格式&#xff0c;它基于ECMAScript&#xff08;欧洲计算机协会制定的js规范&#xff09;的一个子集&#xff0c;采用…

10 - Python文件编程和异常

文件和异常 在实际开发中&#xff0c;常常需要对程序中的数据进行持久化操作&#xff0c;而实现数据持久化最直接简单的方式就是将数据保存到文件中。说到“文件”这个词&#xff0c;可能需要先科普一下关于文件系统的知识&#xff0c;对于这个概念&#xff0c;维基百科上给出…