Java 线程池概念总结(thread pool)

news2025/1/19 8:24:50

一、池化思想的应用

池化思想是一种常见软件设计和优化技术。以下是几个常见池化思想应用场景:

  1. 线程池:线程池是池化思想一个典型应用。通过预先创建一组线程并将它们置于就绪状态,以复用线程减少线程创建和销毁的开销,并提高系统性能和响应速度。

  2. 连接池:连接池是数据库和网络编程中常见应用。通过提前创建一批数据库连接或网络连接并将它们置于可复用状态以避免频繁创建释放连接,从而提高数据库访问和网络通信效率。

  3. 对象池:对象池用于管理和重复使用可复用的对象。例如,数据库连接池、线程安全的缓存池等。通过对象池,可以避免频繁创建和销毁对象,提高系统的性能和资源利用率。

  4. 内存池:频繁内存分配和释放可能会导致内存碎片,降低内存利用效率。内存池将一块连续内存空间划分为多个固定大小的块并维护一个空闲块列表。程序可以从内存池中申请和释放内存块以减少内存碎片和提高内存的分配性能。

  5. 字符串池:字符串池通过将相同的字符串共享在一个池中,减少内存占用和提高字符串比较的速度。Java中字符串常量池就是一种典型字符串池应用。

        这些池化思想的应用都旨在提高系统性能、资源利用率和开发效率,避免重复创建和销毁对象,从而降低系统开销,并提供更好的用户体验。

二、线程池的工作原理

线程池的工作原理可以基本分为以下几个步骤:

  1. 初始化线程池:创建线程池管理器,并设置线程池参数,包括线程数量、工作队列大小等。

  2. 创建线程:根据线程池初始配置,创建指定数量线程并将它们置于就绪状态等待执行任务。

  3. 接收任务:当有任务需要执行时线程池会接收并入队等待处理。任务可以是实现Runnable接口或Callable接口的对象。

  4. 任务调度:线程池中的线程从工作队列中获取任务,按照预设的调度策略进行选择,如先进先出(FIFO)、最近最少使用(LRU)等。

  5. 执行任务:选中的线程会从工作队列中取出任务,并执行任务的run()或call()方法。任务执行完毕后,线程进入空闲状态,等待下一个任务。

  6. 线程回收:当线程池处于空闲状态一段时间后,管理器可能会决定销毁部分线程,以节省系统资源。线程销毁后,线程池的线程数量会相应减少。

  7. 错误处理:线程池会捕获任务执行过程中产生的异常,防止线程因未捕获的异常而崩溃。异常处理策略可以根据具体需求进行自定义,如重新执行、记录日志、忽略等。

        通过上述工作原理,线程池实现了线程的复用和资源的合理利用,使得系统能够更好地处理并发任务,提高性能和响应速度。同时,线程池还能控制线程数量,避免过多的线程造成资源消耗和性能下降,提供了对线程的管理机制。

三、简述一下你对线程池的理解

       如果问到了这样的问题,可以展开说一下线程池如何用、线程池的好处、线程池的启动策略合理利用线程池能够带来三个好处。
        第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
        第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
        第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

        线程池是一种用于管理和复用线程的机制。它由一个线程池管理器、工作队列和一组线程组成。线程池管理器负责创建、销毁和监控线程池中的线程。它根据系统负载和预设条件来动态地调整线程数量,保证线程池的高效利用和合理分配。工作队列用于存储待处理的任务。线程池中的线程从工作队列中取出任务并执行。当任务数量超过线程池的处理能力时,任务会被暂时放入队列中,待有空闲线程时再进行处理。

线程是不是越多越好?

  1. 线程在java中是一个对象,更是操作系统的资源,线程创建、销毁需要时间。如果创建时间+小会时间>执行任务时间就很不合算。
  2. java对象占用堆内存,操作系统线程占用系统内存,根据jvm规范,一个线程默认最大栈大小1M,这个栈空间是需要从系统内存中分配的。线程过多,会消耗很多的内存。
  3. 操作系统需要频繁切换线程上下文(每个线都想被运行),影响性能。

线程池的推出,就是为了方便边的控制线程数量。

        使用线程池时,需要考虑线程数量、工作队列大小以及任务调度策略等因素,以确保线程池能够按预期工作并提供最佳的性能。同时,我们还要注意处理异常情况,避免线程由于未捕获的异常而导致整个线程池崩溃。

为什么不建议使用 Executors静态工厂构建线程池?

        阿里巴巴Java开发手册,明确指出不允许使用Executors静态工厂构建线程池,原因如下:
线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险,说明:Executors返回的线程池对象的弊端如下:

1:FixedThreadPool 和 SingleThreadPool:
允许的请求队列(底层实现是LinkedBlockingQueue)长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM
2:CachedThreadPool 和 ScheduledThreadPool
允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。

        创建线程池的正确姿势:避免使用Executors创建线程池,主要是避免使用其中的默认实现,那么我们可以自己直接调用ThreadPoolExecutor的构造函数来自己创建线程池。在创建的同时,给BlockQueue指定容量就可以了。

private static ExecutorService executor=newThreadPoolExecutor(10,10,60L,TimeUnit.SECONDS,new ArrayBlockingQueue(10));

或者是使用开源类库:开源类库,如apache和guava等。

线程池如何知道一个线程任务已经执行完成?

        线程池通常使用一种称为"Future"的机制来跟踪线程任务的执行状况。

        在Java中,可以通过java.util.concurrent.Future接口来表示异步计算的结果。线程池提交的任务可以返回一个Future对象,在任务执行完成后,可以通过该对象获取任务的执行结果或判断任务是否完成。

具体而言,可以按照以下步骤使用Future来知道线程任务是否已经执行完成:

  1. 提交任务:将要执行的任务提交给线程池,并获得返回的Future对象。

  2. 判断任务状态:通过调用Future的isDone()方法判断任务是否已经完成。如果任务完成,返回true;否则返回false。

  3. 获取任务结果:如果任务已经完成,可以通过调用Future的get()方法获取任务的执行结果。该方法会阻塞当前线程,直到任务完成并返回结果。

        需要注意的是,如果任务还未完成,调用get()方法会使当前线程阻塞,直到任务执行完成。如果不希望阻塞当前线程,可以使用isDone()方法轮询判断任务状态,或者使用带有超时参数的get()方法来等待一段时间后获取结果。

        总之,通过使用Future对象,线程池可以方便地跟踪和获取线程任务的执行状态和结果,从而实现对任务的管理和控制。

参考:

Java 中线程池的 7 种创建方式! - 磊哥|www.javacn.site - 博客园 (cnblogs.com)

Java线程池实现原理及其在美团业务中的实践 - 美团技术团队 (meituan.com)

JUC线程池: ThreadPoolExecutor详解 | Java 全栈知识体系 (pdai.tech)

线程池面试题 - 小魚人 - 博客园 (cnblogs.com)

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

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

相关文章

PY32F003F18按键输入

一、PY32F003F18的GPIO介绍 1、PY32F003F18的18个I/O,均可作为外部中断; 2、每个GPIO都可以由软件配置为输出: 1)、推挽输出(push-pull) 2)、开漏极输出(open drain) 注意:驱动电流为8mA; 3、每个GPIO都可以由软件配置为输入: 1)、…

视频图像处理算法opencv在esp32及esp32s3上面的移植,也可以移植openmv

opencv在esp32及esp32s3上面的移植 Opencv简介 OpenCV是一个基于Apache2.0许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上,它轻量级而且高效——由一系列 C 函数和少量…

02-请解释一下Java的内存模型和happens-before规则?【Java面试题总结】

请解释一下Java的内存模型和happens-before规则? 概念:Java内存模型,简称JMM,是一种定义了多线程程序中内存访问行为的规范。它定义了线程如何与主内存和工作内存进行交互,以及如何保证多线程程序的正确性和可见性。J…

聚鑫数藏平台——引领数字资产管理新风向

随着数字经济的飞速发展,新金融生态应运而生。区块链技术的崭新突破,使数字资产的重要性日益凸显,为投资者带来了前所未有的机遇和挑战。在此背景下,聚鑫数藏平台横空出世,引领着数字资产管理的新风向。 聚鑫数藏平台&…

2023数学建模国赛四天速成计划来啦!(内含大量资料)

大家好呀。高教社杯全国大学生数学建模竞赛(下称国赛)9.7日下午6点就正式开始了: 在这里给大家带来一个五天的速成计划啦!大家可以收藏本文章或者转发到你们队友群哈,此外我还会发放很多资料给大家,注意&am…

数据结构|栈和队列以及实现

栈和队列 一、栈1.1栈的概念及结构1.2栈的实现 二、队列2.1队列的概念及结构2.2队列的实现 一、栈 1.1栈的概念及结构 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和数据删除的一端称为栈顶,另一端称为栈…

UE4 植物生长

这个可以改变SplineMesh朝向

leetcode 724. 寻找数组的中心下标

2023.9.3 本题先 求出数组总和sum&#xff0c;再寻找数组的中心下标&#xff1a;if(sum - temp -nums[i] temp) return i; 代码如下&#xff1a; class Solution { public:int pivotIndex(vector<int>& nums) {//求数组元素总和int sum 0; for(int num : nums…

【C++技能树】继承概念与解析

Halo&#xff0c;这里是Ppeua。平时主要更新C&#xff0c;数据结构算法&#xff0c;Linux与ROS…感兴趣就关注我bua&#xff01; 继承 0. 继承概念0.1 继承访问限定符 1. 基类和派生类对象赋值兼容转换2. 继承中的作用域3. 派生类中的默认成员函数4.友元5.继承中的静态成员6.菱…

lenovo联想笔记本小新 潮7000-14IKBR 2018款(81GA)原装出厂Windows10系统镜像

自带所有驱动、出厂主题壁纸LOGO、Office办公软件、联想电脑管家等预装程序 链接&#xff1a;https://pan.baidu.com/s/1ynP4d5z7MPF9l5U5lCjDzQ?pwdhjvj 提取码&#xff1a;hjvj 所需要工具&#xff1a;16G或以上的U盘 文件格式&#xff1a;ISO 文件大小&#x…

2.4 关系数据库

思维导图&#xff1a; 前言&#xff1a; 这段话描述了“关系数据库”及其背后的理论基础。首先&#xff0c;我们来拆分这段话并逐步解释每部分。 关系数据库是采用关系模型作为数据组织方式的数据库。 这句话的关键是“关系模型”。关系模型是一种表示和操作数据库的理论模型…

软考备考-程序员-考试介绍和考试大纲

软考程序员-考试介绍和考试大纲 全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试 计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff08;以下简称计算机软件资格考试&#xff09;是原中国计算机软件专业技术资格和水平考试&#xff0…

第三方系统测试怎么做?有些什么流程

系统测试 软件系统研发出来以后&#xff0c;产品的各个模板功能是否能够正常运转需要进行软件系统测试。而对于普通的互联网企业来说&#xff0c;软件测试的各项工作已经超出开发工作内容&#xff0c;由开发人员进行系统测试不仅需要耗费软件团队精力&#xff0c;可能测试效果…

Pyecharts数据可视化(三)

目录 1.绘制词云图 2.绘制桑基图 3.绘制平行坐标图 4.绘制结点图 5.绘制地图 本文主要介绍了如何利用Pyecharts绘制词云图、桑基图、平行坐标图、节点图和地图&#xff0c;虽然这些图平时不是很常用&#xff0c;但是看起来还是比较好看的&#xff0c;如果放在论文当中&am…

leetcode793. 阶乘函数后 K 个零(java)

阶乘函数后 K 个零 题目描述二分法代码模拟 题目描述 难度 - 困难 阶乘函数后 K 个零 f(x) 是 x! 末尾是 0 的数量。回想一下 x! 1 * 2 * 3 * … * x&#xff0c;且 0! 1 。 例如&#xff0c; f(3) 0 &#xff0c;因为 3! 6 的末尾没有 0 &#xff1b;而 f(11) 2 &#xf…

Bito使用手册

第一步&#xff1a;输入网站 https://alpha.bito.co/bitoai/ 第二步&#xff1a;填写邮箱 第三步&#xff1a;登录邮箱&#xff0c;获取验证码 第四步&#xff1a;填写验证码 第五步&#xff1a;完成

Scala的函数式编程与高阶函数,匿名函数,偏函数,函数的闭包、柯里化,抽象控制,懒加载等

Scala的函数式编程 函数式编程 解决问题时&#xff0c;将问题分解成一个一个的步骤&#xff0c;将每个步骤进行封装&#xff08;函数&#xff09;&#xff0c;通过调用这些封装好的步骤&#xff0c;解决问题。 例如&#xff1a;请求->用户名、密码->连接 JDBC->读取…

zabbix监控平台部署

目录 前言 一、zabbix的基本概述 &#xff08;一&#xff09;、zabbix的工作流程 &#xff08;二&#xff09;、zabbix的构成 &#xff08;三&#xff09;、zabbix的监控对象 &#xff08;四&#xff09;、zabbix的常用术语 &#xff08;五&#xff09;、zabbix进程详解…

植物根系基因组与数据分析

1.背景 这段内容主要是关于植物对干旱胁迫的反应&#xff0c;并介绍了生活在植物体内外以及根际的真菌和细菌的作用。然而&#xff0c;目前对这些真菌和细菌的稳定性了解甚少。作者通过调查微生物群落组成和微生物相关性的方法&#xff0c;对农业系统中真菌和细菌对干旱的抗性…

windows 2012服务器配置nginx后无法访问域名的问题

环境&#xff1a;Windows 2012 R2 Nginx 问题&#xff1a;确认域名解析到服务器ip已生效&#xff08;通过ping域名地址确认域名已指向该ip&#xff09;&#xff0c;确认nginx配置无误&#xff08;绑定域名、配置端口、配置网站文件目录&#xff09;&#xff0c;但无法从外网访…