三、Java并发 Java 线程池 ( Thread Pool )
一、前言
本文我们将讲解 Java 中的线程池 ( Thread Pool ),从 Java 标准库中的线程池的不同实现开始,到 Google 开发的 Guava 库的前世今生
注:本章节涉及到很多前几个章节中阐述的知识点。我们希望你是按照顺序阅读下来的,不然有些知识会一头雾水。
Java 语言的实现中,把 Java 线程一一映射到操作系统级的线程,而后者是操作系统的资源,这意味着,如果开发者毫无节制地创建线程,那么线程资源就会被快速的耗尽。
在Windows 操作系统上,每个线程要预留出 1m 的内存空间,意味着 2G 的内存理论上做多只能创建 2048 个线程。而在 Linux 上,最大线程数由常量 PTHREAD_THREADS_MAX 决定,一般为 1024。
出于模拟并行性的目的,Java 线程之间的上下文切换也由操作系统完成。因为线程上下文切换需要消耗时间,所以,一个简单的观点是:产生的线程越多,每个线程花在实际工作上的时间就越少。
为什么会有线程上下文切换?
一台电脑,运行起来后,它的 CPU 是固定的,05 年之前,还是单核时代,也就是一次只能运行一个线程,虽然随着时间的推移,现在的 CPU 已经有很多个核心,比如 8 核 16 核之类的。但相比于一个应用程序能够创建的线程数,那真的是太少了。而每个核心一次只能运行一个线程,所以多个线程需要运行时就需要来回不停的在多个线程间切换,这就是线程之间的上下文切换。
为了节制创建线程的数量,也为了节省创建线程的开销,因此提出了线程池的概念。线程池模式有助于节省多线程应用程序中的资源,还可以在某些预定义的限制内包含并行性。
当我们使用线程池时,我们可以以并行任务的形式编写并发代码并将其提交到线程池的实例中执行。
这个线程池实例控制了多个重用线程以执行这些任务。
这种线程池模式,允许我们控制应用程序创建的线程数,生命周期,以及计划任务的执行并将传入的任务保留在队列中。
二、 Java 中的线程池
Executors/Executor/ExecutorService
关系
首先介绍一下他们三者之间的关系
Executor, ExecutorService 都是接口,ExecutorService继承于Executor,Executors是工具类,他提供对ThreadPoolExecutor的封装产生ExecutorService的具体实现类。
图一:

图一可以看出 ExecutorService继承于Executor,且 Executors 是一个帮助类几个用于创建线程池
图二:

图二可以看出 Executors几个new的方法 返回的基本都是ExecutorService
一句话他们之间的关系就是 Executor, ExecutorService 都是接口,ExecutorService继承于Executor,Executors是工具类,他提供对ThreadPoolExecutor的封装,会产生几种线程池供大家使用。
Executors/Executor
Executors 是一个帮助类,提供了创建几种预配置线程池实例的方法。如果你不需要应用任何自定义的微调,可以调用这些方法创建默认配置的线程池,因为它能节省很多时间和代码。
Executor 和 ExecutorService 接口则用于与 Java 中不同线程池的实现协同工作。通常,你应该将代码与线程池的实际实现分离,并在整个应用程序中使用这些接口。
Executor 接口提供了一个 execute() 方法将 Runnable 实例提交到线程池中执行。
下面的代码是一个快速示例,演示了如何使用 Executors API 获取包含了单个线程池和无限队列支持的 Executor 实例,以便按顺序执行任务。
Executor executor = Executors.newSingleThreadExecutor();
获取了Executor 示例后,我们就可以使用 execute() 方法将一个只在屏幕上打印 Hello World 的任务提交到队列中执行。
executor.execute(() -> System.out.println("Hello World"));
上面这个示例使用了 lambda ( Java 8特性 )提交任务,JVM 会自动推断该任务为 Runnable
我们在Java Shell 演示下上面的代码
jshell> import java.util.concurrent.*jshell> Executor executor = Executors.newSingleThreadExecutor();
executor ==> java.util.concurrent.Executors$FinalizableDelegatedExecutorService@1e127982jshell> executor.execute(() -> System.out.println("Hello World"));jshell> Hello World
jshell>
ExecutorService
ExecutorService 接口则包含大量用于控制任务进度和管理服务终止的方法。我们可以使用此接口来提交要执行的任务,还可以使用此接口返回的 Future 实例控制任务的执行。
下面的示例中,我们创建了一个 ExecutorService 的实例,提交了一个任务,然后使用返回的 Future 的 get() 方法等待提交的任务完成并返回值。
ExecutorService executorService = Executors.newFixedThreadPool(10);
Future<String> future = executorService.submit(() -> "Hello World");
// 一些其它操作
String result = future.get();
在实际使用时,我们并不会立即调用 future.get() 方法,可能会等待一些时间,推迟调用它直到我们需要它的值用于计算等目的。
ExecutorService 中的 submit() 方法被重载为支持 Runnable 或 Callable ,它们都是功能接口,可以接收一个 lambdas 作为参数( 从 Java 8 开始 ):
- 使用 Runnable 作为参数的方法不会抛出异常也不会返回任何值 ( 返回 void )
- 使用 Callable 作为参数的方法则可以抛出异常也可以返回值。
如果想让编译器将参数推断为 Callable 类型,只需要 lambda 返回一个值即可。
ExecutorService 接口的更多使用范例和特性,你可以访问前面的章节 一文秒懂 Java ExecutorService。
相关文章:
三、Java并发 Java 线程池 ( Thread Pool )
一、前言 本文我们将讲解 Java 中的线程池 ( Thread Pool ),从 Java 标准库中的线程池的不同实现开始,到 Google 开发的 Guava 库的前世今生 注:本章节涉及到很多前几个章节中阐述的知识点。我们希望你是按照顺序阅读下来的,不然…...
zabbix安装配置与使用
zabbix Zabbix的工作原理如下: 监控部分: Zabbix Agent安装在各个需要监控的主机上,它以主配置的时间间隔(默认60s)收集主机各项指标数据,如CPU占用率、内存使用情况等。 通讯部分: Agent会把收集的数据通过安全通道(默认10051端口)发送到Zabbix Server。Server会存储这些数…...
第3关:命题逻辑推理
任务描述 相关知识 实验用例 实验原理和方法 编程要求 测试说明 任务描述 本关任务:用命题逻辑推理的方法解决逻辑推理问题。加深对命题逻辑推理方法的理解。 相关知识 为了完成本关任务,你需要掌握:1.命题符号化,2.命题推理。 …...
第三份代码:VoxelNet的pytorch实现
VoxelNet是点云体素化处理的最开始的网络结构设计,通过完全弄明白整个VoxelNet的pytorch实现是非常有必要的。 参考的代码是这一份:GitHub - RPFey/voxelnet_pytorch: modification of voxelnet 参考文章:VoxelNet论文解读和代码解析_voxel…...
Backtrader-Broker05
本系列是使用Backtrader在量化领域的学习与实践,着重介绍Backtrader的使用。Backtrader 中几个核心组件: Cerebro:BackTrader的基石,所有的操作都是基于Cerebro的。Feed:将运行策略所需的基础数据加载到Cerebro中&…...
分布式和微服务系统区别
一、分布式是更广泛的概念,指将计算分布在多个物理节点上的系统。 适用于需要高可用性、高性能、可扩展性的系统。 应用场景:分布式数据库—数据高可用存储、分布式缓存—提升数据访问速度 分布式计算框架—大规模数据计算、分布式文件系统—海量数据的…...
ElementUI el-table 多选以及点击某一行的任意位置就勾选上
1. 需求 在el-table中,需要实现多选功能,并且点击某一行的任意位置就勾选上,而不是点击复选框才勾选上。 2. 实现思路 在el-table中添加ref属性,用于获取表格实例。在el-table-column中添加type"selection"属性&…...
博物馆3D数字化的优势有哪些?
博物馆的3D数字化进程正不断向前推进,这一创新技术在提升观展体验、促进文化传播以及加强文物保护方面,均展现出了显著的优势。 一、观展体验的革命性提升 1、动态与多角度展示: 3D云展览利用先进的数字化技术,使文物能够以动态…...
Hi3516/Hi3519DV500移植YOLOV5、YOLOV6、YOLOV7、YOLOV8开发环境搭建--YOLOV5工程编译移植到开发板测试--(5)
专栏链接如下: Hi3516/Hi3519DV500移植YOLOV5、YOLOV6、YOLOV7、YOLOV8开发环境搭建--安装Ubuntu18.04--(1) Hi3516/Hi3519DV500移植YOLOV5、YOLOV6、YOLOV7、YOLOV8开发环境搭建--安装开发环境AMCT、依赖包等--(2)…...
springboot揭秘00-基于java配置的spring容器
文章目录 【README】【1】基本概念:Configuration与Bean【2】使用AnnotationConfigApplicationContext实例化spring容器【2.1】使用java配置简单构建spring容器【2.1.1】AnnotationConfigApplicationContext与Component及JSR-330注解类一起使用 【2.2】使用register…...
docker配置mysql
手动拉取 MySQL 镜像 docker pull mysql 创建并运行 MySQL 容器(docker run) docker run -d \--name mysql \-p 3306:3306 \-e TZAsia/shanghai \-e MYSQL_ROOT_PASSWORD123 \mysql -d:以守护进程(daemon)模式运行…...
说说Dubbo有哪些核心组件?
说说Dubbo有哪些核心组件? 简单来说,就是服务提供者Provider,服务消费者Consumer,服务注册中心Registry,服务监控器Monitor,通信协议Protocol Dubbo 是一款高性能、轻量级的开源 Java RPC 框架࿰…...
视频文件损坏无法播放怎么办?有什么办法可以修复视频吗?
人人都是自媒体的时代,我们已不再满足单纯的图片及声音传播,拍摄短视频的需求日渐增高。但随之也带来了许多问题,比如:拍摄的视频在保存或转移拷贝过程出现问题导致视频文件损坏无法播放。遇到这种情况时怎么办?有什么…...
flutter ios ffi 调试 .a文件 debug可以 release 不行
在 Flutter 中使用 FFI(Foreign Function Interface)时,如果你在调试模式下能够正常工作,而在发布模式下却遇到问题,使用Object-c原生调用可以使用,开启去掉优化也可以,可能的原因在发布模式下&…...
ADB指定进程名称kill进程
adb shell ps | grep <process_name> | awk {print $2} | xargs adb shell killadb shell ps:列出所有正在运行的进程。grep <process_name>:筛选出包含指定进程名称的行。awk ‘{print $2}’:提取输出中的第二列(通常…...
巨好看的登录注册界面源码
展示效果 源码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><meta name"viewport" content"widthdevic…...
Python 数据结构
1.概念 数据结构是计算机科学中的一个核心概念,它是指数据的组织、管理和存储方式,以及数据元素之间的关系。数据结构通常用于允许高效的数据插入、删除和搜索操作。 数据结构大致分为几大类: 线性结构:数组、链表、栈、队列等…...
计算机网络八股文个人总结
1.TCP/IP模型和OSI模型的区别 在计算机网络中,TCP/IP 模型和 OSI 模型是两个重要的网络协议模型。它们帮助我们理解计算机通信的工作原理。以下是它们的主要区别,以通俗易懂的方式进行解释: 1. 模型层数 OSI 模型:有 7 层&#…...
Flutter使用share_plus是提示发现了重复的类
问题描述 我现在下载了share_plus包后发现代码编译不通过,并提示Duplicate class kotlin.collections.jdk8.CollectionsJDK8Kt found in modules jetified-kotlin-stdlib-1.8.22 (org.jetbrains.kotlin:kotlin-stdlib:1.8.22) and jetified-kotlin-stdlib-jdk8-1.7…...
【Linux】编辑器vim 与 编译器gcc/g++
目录 一、编辑器vim: 1、对vim初步理解: 2、vim的模式: 3、进入与退出: 4、vim命令模式下的指令集: 移动光标: 删除: cv: 撤销: 其他: 5、vim底行模…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...
DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...
嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)
目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 编辑编辑 UDP的特征 socke函数 bind函数 recvfrom函数(接收函数) sendto函数(发送函数) 五、网络编程之 UDP 用…...
JS红宝书笔记 - 3.3 变量
要定义变量,可以使用var操作符,后跟变量名 ES实现变量初始化,因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符,可以创建一个全局变量 如果需要定义…...
麒麟系统使用-进行.NET开发
文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的,如果需要进行.NET开发,则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET,所以要进…...
