当前位置: 首页 > news >正文

Java线程池使用与原理解析(线程池优点、使用方法、参数含义及线程池运转机制)

为什么要使用线程池?

JDK1.5后JUC包添加了线程池相关接口,在Java诞生之初并没有线程池这个概念。刚开始Java程序都是自行创建线程去处理任务。随着应用使用的线程越来越多,JDK开发者们发现有必要使用一个统一的类来管理这些线程,从而有效提高线程的执行效率,减少创建、销毁线程的开销。

大量线程的创建、销毁是非常消耗资源的。创建线程需要消耗一定的内存、CPU资源,大量的线程也会导致大量的线程上下文切换,上下文切换代码也是相当大的,过多的线程导致频繁切换更是可能使系统性能急速下降。另外操作系统对每个进程能创建的线程数也是有限制的,不可能无限创建。但是大量任务也不可能只在主线程处理吧,这样也太慢了。比如下面的例子,创建上万的线程,每个线程打印一下线程名字,观察一下任务管理器,CPU直接用完。这只是简单的任务,要是复杂长时间的任务,整个操作系统可能都会受到影响(CPU利用率长时间下不来,影响其他程序)

public class BadMultiThreadTest {public static void main(String[] args) {Runnable r = () -> {System.out.println("ThreadName-" + Thread.currentThread().getName());};//过多创建线程导致系统资源消耗严重for (int i = 0; i < 10000; i++) {Thread thread = new Thread(r);thread.start();}}
}

线程池就是为了解决上述问题出现的,解决问题的思路很清晰,就是创建好一定数量的线程,有任务来了就用这些线程来执行任务,任务过多把池里面的线程都占用了就放队列排队等候其他任务执行,一旦有空闲线程就可以从队列里面取出任务并执行。有了可控的线程池,系统就不会处于一种可能随时被大量并发导致线程大量创建,最终压跨系统的危险中。

如何使用线程池?

使用线程池去改造上面的例子:

public class MultiThreadPoolTest {public static void main(String[] args) {ExecutorService executorService = Executors.newFixedThreadPool(10);for (int i = 0; i < 10000; i++) {executorService.execute(() -> {System.out.println("ThreadName-" + Thread.currentThread().getName());});}}
}

这次再观察任务管理器,这次CPU占用不会说飙长,而是相对平稳。打印的线程名称就是在ThreadName-pool-1-thread-1到ThreadName-pool-1-thread-10之间变化,说明这一万个任务都是这10个线程处理的。 

线程池的参数含义

上面的例子简单的使用了Excutors工具类来创建了一个固定线程数的线程池。这个工具类还可以创建单线程线程池、可缓存线程池、定时执行任务的线程池等。这些线程池的创建事实上都是在创建一个ThreadPoolExecutor实例,只是通过传递不同参数,实现不同的线程池效果而已。如果我们把里面的参数都搞明白,我们就可以根据实际需求去自定义线程池,实际开发中,我们都应该使用自定义的线程池去处理相关业务,这样能最大提高线程池使用效率,提高系统性能。当然,这还得靠我们对业务的理解,从而定义出合理的线程池。

通过下面这句代码,跟踪源码

Executors.newFixedThreadPool(10);

最终调用的函数如下,它包含了线程池的所有参数注释:

    /*** Creates a new {@code ThreadPoolExecutor} with the given initial* parameters.** @param corePoolSize the number of threads to keep in the pool, even*        if they are idle, unless {@code allowCoreThreadTimeOut} is set* @param maximumPoolSize the maximum number of threads to allow in the*        pool* @param keepAliveTime when the number of threads is greater than*        the core, this is the maximum time that excess idle threads*        will wait for new tasks before terminating.* @param unit the time unit for the {@code keepAliveTime} argument* @param workQueue the queue to use for holding tasks before they are*        executed.  This queue will hold only the {@code Runnable}*        tasks submitted by the {@code execute} method.* @param threadFactory the factory to use when the executor*        creates a new thread* @param handler the handler to use when execution is blocked*        because the thread bounds and queue capacities are reached* @throws IllegalArgumentException if one of the following holds:<br>*         {@code corePoolSize < 0}<br>*         {@code keepAliveTime < 0}<br>*         {@code maximumPoolSize <= 0}<br>*         {@code maximumPoolSize < corePoolSize}* @throws NullPointerException if {@code workQueue}*         or {@code threadFactory} or {@code handler} is null*/public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize ||keepAliveTime < 0)throw new IllegalArgumentException();if (workQueue == null || threadFactory == null || handler == null)throw new NullPointerException();this.acc = System.getSecurityManager() == null ?null :AccessController.getContext();this.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler;}

 下面简单总结一下参数的含义:

参数名称含义
corePoolSize
核心线程数
maximumPoolSize
最大线程数
keepAliveTime+时间单位
空闲线程存活时间
workQueue
任务队列
threadFactory
创建线程的工厂类
handler
被拒绝任务处理器

线程池处理任务的流程

看一下下面的流程图就能清晰知道任务从被提交再到被线程池中线程执行的流程了。

待补充...

使用线程池的优点

根据上面可以简略总结出使用线程池的几点优点:

  • 解决线程创建、销毁等生命周期系统消耗过大问题。因为线程池中的线程一旦创建过,核心线程是会一直驻留在池中待用的,这样任务来了后,直接可以执行,消除了创建线程的系统开销。系统响应更及时,使用更丝滑。
  • 线程池使得系统可控性更强。它避免了系统资源使用不当导致系统崩溃,能更合理的使用CPU和内存资源。

相关文章:

Java线程池使用与原理解析(线程池优点、使用方法、参数含义及线程池运转机制)

为什么要使用线程池&#xff1f; JDK1.5后JUC包添加了线程池相关接口&#xff0c;在Java诞生之初并没有线程池这个概念。刚开始Java程序都是自行创建线程去处理任务。随着应用使用的线程越来越多&#xff0c;JDK开发者们发现有必要使用一个统一的类来管理这些线程&#xff0c;…...

mybatis入门配置

mybatis mybatis是一款持久层框架&#xff0c;用于简化JDBC开发 持久层&#xff1a;负责将数据保存到数据库的那一层代码JavaEE的三层架构&#xff1a;表现层、业务层、持久层、&#xff0c;就相当与mvc设计模式过程中的Controller、service、dao 1.创建一个maven模块&#…...

黑客入门(超级详细版)

据我了解&#xff0c;“黑客”大体上应该分为“正”、“邪”两类&#xff0c;正派黑客依靠自己掌握的知识帮助系统管理员找出系统中的漏洞并加以完善&#xff0c;而邪派黑客则是通过各种黑客技能对系统进行攻击、入侵或者做其他一些有害于网络的事情&#xff0c;因为邪派黑客所…...

Java多线程(三)---synchronized、Lock和volatile

Java内存模型&#xff08;非JVM&#xff09;Java内存模型(Java Memory Model简称JMM)&#xff0c;是一种共享内存模型&#xff0c;是多线程的东西&#xff0c;并不是JVM&#xff08;Java Virtual Machine(Java虚拟机)的缩写&#xff09;&#xff0c;这是俩玩意儿&#xff01;&a…...

JVM-Java内存区域

运行时数据区&#xff1a;1、程序计数器&#xff1a;当前线程所执行的字节码指令的行号指示器。在Java虚拟机的概念模型里&#xff0c;字节码解释器的工作就是通过改变这个计数器的值来选取下一条需要执行的字节码指令&#xff0c;它是程序控制流的指示器&#xff0c;分支、循环…...

毕业季,毕业论文查重,paper系列五个免费查重网站推荐

推荐五个常用的免费查重网站 注意&#xff1a; &#xff08;1&#xff09;这些网站基本上都可以通过关注公众号或者转发等来获取免费查重机会&#xff0c;但有些也会有字数限制。每个网站的数据库可能不同&#xff0c;所以建议大家多换几个平台查一查&#xff0c;反正是免费的…...

破解票房之谜:为何高票房电影绕不过“猫眼们”?

如此火爆的春节档很多&#xff0c;如此毁誉参半的春节档鲜有。2023开年&#xff0c;集齐张艺谋、沈腾的《满江红》&#xff0c;以及有票房前作打底的《流浪地球2》接连两部春节档电影票房进入前十&#xff0c;为有些颓靡的中国电影市场注入了一针“强心剂”。与票房同样热闹起来…...

订单服务-----遇到的问题及解决方案

订单服务的问题及解决方案问题1&#xff1a;Feign远程调用时丢失请求头编辑出现这个Feign远程调用时丢失请求头的问题是因为Feign在远程调用的时候会创建一个新的请求&#xff0c;但是这个新的请求里啥都没有&#xff0c;没有cookie值&#xff0c;而这个cookie值里有成功登录后…...

项目经理如何度量项目?及项目度量指标实例【静说】

度量项目是项目经理的一个重要职责&#xff0c;通过度量项目&#xff0c;项目经理可以了解项目的进展情况&#xff0c;及时发现问题并采取相应的措施&#xff0c;以确保项目能够按时、按质、按预算完成。 分享给大家一些常见的项目度量指标&#xff1a; 1. 项目进度&#xff…...

我们应该如何优雅的处理 React 中受控与非受控

引言 大家好&#xff0c;我是19组清风。有段时间没有和大家见面了&#xff0c;最近因为有一些比较重要的事情&#xff08;陪女朋友和换了新公司&#xff09;在忙碌所以销声匿迹了一小段时间&#xff0c; 后续会陆陆续续补充之前构建 & 编译系列中缺失的部分&#xff0c;提…...

力扣热题100Day06:20. 有效的括号,21. 合并两个有序链表,22. 括号生成

20. 有效的括号 题目链接&#xff1a;20. 有效的括号 - 力扣&#xff08;Leetcode&#xff09; 思路&#xff1a;使用栈 &#xff08;1&#xff09;遇到左括号就将其对应的右括号压入到栈中 &#xff08;2&#xff09;如果遇到右括号 a. 如果弹出的元素与当前不等&#xff…...

【Yolov5】保姆级别源码讲解之-推理部分detect.py文件

推理部分之detect.py文件讲解1.下载Yolov5的源码2. 主函数讲解3.文件标头的注释4. main函数的5. run函数5.1 第一块参数部分5.2第二块&#xff0c;传入数据预处理5.3 第三块创建文件夹5.4 第四块 加载模型的权重5.5 第五块 Dataloader 加载模块5.6 第六块 推理部分 Run inferen…...

无重叠区间-力扣435-java贪心策略

一、题目描述给定一个区间的集合 intervals &#xff0c;其中 intervals[i] [starti, endi] 。返回 需要移除区间的最小数量&#xff0c;使剩余区间互不重叠 。示例 1:输入: intervals [[1,2],[2,3],[3,4],[1,3]]输出: 1解释: 移除 [1,3] 后&#xff0c;剩下的区间没有重叠。…...

Python使用VTK对容积超声图像进行体绘制(三维重建)

目录VTK简介什么是体绘制&#xff1f;体绘制效果图流程CodeQ&AReferenceVTK简介 VTK&#xff08;Visualization Toolkit&#xff09;是一个用于3D计算机图形学、图像处理和可视化的开源软件包。它包括一组C类和工具&#xff0c;可以让用户创建和处理复杂的3D图形和数据可视…...

JAVA设计模式之工厂模式讲解

目录 前言 开始表演 前言 Java中使用工厂模式的主要原因是为了实现代码的灵活性和可维护性。工厂模式是一种创建型设计模式&#xff0c;它提供了一种将对象的创建和使用进行分离的方式。具体来说&#xff0c;工厂模式可以将对象的创建过程封装在一个独立的工厂类中&#xff…...

近万字概述L3及以上自动驾驶故障运行和故障安全机制

本文描述了对ADS的FO和FS机制的评估方法。当系统不能按预期运行时,ADS将使用FO和FS机制。这些机制使ADS能够在最大程度上达到使车辆及其乘员脱离危险的MRC。定义、测试和验证实现MRC的FO和FS策略是确保ADS安全运行和部署的重要步骤。 MRC在SAE J3016中被定义为: 用户或ADS在…...

kafka入门到精通

文章目录一、kafka概述&#xff1f;1.定义1.2消息队列1.2.1 传统消息队列的使用场景1.2.2 消息队列好处1.2.3 消息队列两种模式1.3 kafka基础架构二、kafka快速入门1.1使用docker-compose安装kafka1.2测试访问kafka-manager1.3 查看kafka版本号1.4 查看zookeeper版本号1.5 扩展…...

es-09模糊查询

模糊查询 前缀搜索&#xff1a;prefix 概念&#xff1a;以xx开头的搜索&#xff0c;不计算相关度评分。 注意&#xff1a; 前缀搜索匹配的是term&#xff0c;而不是field。前缀搜索的性能很差前缀搜索没有缓存前缀搜索尽可能把前缀长度设置的更长 语法&#xff1a; GET <ind…...

57 - 深入解析任务调度

---- 整理自狄泰软件唐佐林老师课程 文章目录1. 问题1.1 思考1.2 实例分析&#xff1a;问题分析及解决2. 深入讨论2.1 任务调度的定义2.2 关于调度算法的分类2.3 什么时候进行任务调度2.4 任务的分类2.5 关于优先级调度2.6 问题2.7 调度算法的终极目标2.8 课后扩展1. 问题 系统…...

CAN总线开发一本全(3) - 微控制器集成的FlexCAN外设

CAN总线开发一本全&#xff08;3&#xff09; - 微控制器集成的FlexCAN外设 苏勇&#xff0c;2023年2月 文章目录CAN总线开发一本全&#xff08;3&#xff09; - 微控制器集成的FlexCAN外设引言硬件外设模块系统概要总线接口单元 - 寄存器清单数据结构 - 消息缓冲区MB初始化过…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

SpringTask-03.入门案例

一.入门案例 启动类&#xff1a; package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 &#x1f4dd; 在上一篇文章中&#xff0c;我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源&#xff0c;方便后续将资源打包到一个可执行文件中。 2.embed介绍 &#x1f3af; Go 1.16 引入了革命性的 embed 包&#xff0c;彻底改变了静态资源管理的…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...