JAVA中的线程池说明一

目录

1.为什么需要线程池?

2.什么是线程池?

3.标准库中的线程池

4.实现自定义线程池


1.为什么需要线程池?

       线程的存在意义在于解决并发编程中进程开销过大的问题,因此引入了线程,也被称为"轻量级线程"。相比于创建进程,创建线程更加高效;同样地,销毁线程比销毁进程更高效,调度线程比调度进程更高效。

       在许多情况下,使用多线程可以替代进程来实现并发编程。然而,随着并发程度的提高和对性能要求的提高,频繁创建和销毁线程会导致线程创建变得不那么轻量。为了降低创建和销毁线程的开销,我们可以使用线程池来管理线程资源。

2.什么是线程池?

       线程池是一种管理线程的机制,它预先创建一定数量的线程,并将它们放入一个池中。当需要执行任务时,线程池会从池中选择一个空闲的线程来执行任务,而不是每次都创建新的线程。一旦任务完成,线程会被归还到线程池中,等待下一次使用。

       在之前我们也了解过,相关的池化技术,字符串常量池,数据库连接池,HTTP连接池等,池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率。

线程池的主要优点包括:

  • 提高性能,降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
  • 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
  • 提高线程的可管理性。线程池可以限制同时运行的线程数量,避免过多的线程导致系统资源耗尽,使用线程池可以进行统一的分配,调优和监控。

上面我们说到:

将线程从线程池里获取,用完后还给线程池,这两个动作比创建/销毁进程更高效

那这里的原因是什么呢?

       是因为创建/销毁进程是交由操作系统内核完成的,从线程从线程池里获取,用完后还给线程池,是我们自己用户的代码就可以实现的,不必交给内核操作。

那什么是操作系统内核呢?

       操作系统内核是操作系统的核心部分,它负责管理系统的资源、调度进程和线程的执行、处理硬件设备等。它是操作系统与计算机硬件之间的接口,提供了系统级别的服务和功能。

       比如在银行大厅里,用户们可以自由地操作,这就像计算机程序中的"用户态"。在用户态下,执行的是程序员编写的代码,用户可以按照自己的意愿进行各种操作,完全由程序员来决定。

       然而,有些特定的任务必须在银行柜台内完成,客户无法直接进入柜台,必须通过银行工作人员来执行这些任务。这与计算机程序中的"内核态"相似。内核态的操作都在操作系统的内核中进行,内核提供给程序员一些应用程序接口(API),称为系统调用。程序员可以通过调用这些API来驱动内核完成某些工作。系统调用的内容直接与内核的代码相关,这部分代码不受程序员的控制,完全由内核自行处理。

       与内核相比,用户态的程序行为是可控的。如果用户想要立即完成某项工作,可以直接在用户态下进行。但是,如果想要通过内核从系统中创建一个新的线程,就需要使用系统调用,让内核来执行这一操作。然而,我们无法确定内核当前正在处理多少其他任务。例如,如果你希望柜台工作人员帮你存钱,但前面可能有很多人正在排队等待服务。因此,当我们使用系统调用来执行内核代码时,无法确切知道内核将执行哪些具体操作,这使得整个过程相对"不可控"。

3.标准库中的线程池

       在Java标准库中,也有现成的线程池,可以直接进行使用,下面这个代码是指,创建一个线程池,池子里现成数目固定为10个。

    public static void main(String[] args) {//创建一个线程池,池子里现成数目固定为10个ExecutorService pool = Executors.newFixedThreadPool(10);for (int i = 0; i < 1000; i++) {int n = i;pool.submit(new Runnable() {@Overridepublic void run() {System.out.println("hello" + n);}});}}

ExecutorService pool = Executors.newFixedThreadPool(10);

       在这个例子中,我们使用了`newFixedThreadPool()`方法创建了一个固定大小的线程池。这种设计模式被称为"工厂模式"。

       线程池提供了一个重要的方法`submit`,可以用来向线程池提交多个任务。当我们运行这段代码时,会发现主线程已经结束,但是线程池中的线程仍然在运行,这是因为这些线程都是前台线程,它们会阻止线程池的关闭。

       需要注意的是,这里我们向线程池提交了1000个任务,这些任务将被10个线程平均分配。每个线程大约执行100个任务,但由于每个任务执行时间相近,因此每个线程处理的任务数量也大致相同。可以认为这1000个任务被放入一个队列中,10个线程依次从队列中取出任务并执行。

int n = i;

       这里需要再定义一个变量n,而不是直接使用i的原因是变量捕获。

       在主线程中,i是一个局部变量,当主线程的for循环结束时,i将被销毁。然而,有可能主线程的for循环结束,但当前的run任务尚未在线程池中执行。

       为了避免作用域差异导致后续执行run方法时i已经销毁,我们需要进行变量捕获,即将主线程中的i值传递给当前run方法所在的线程。这样,即使主线程的i被销毁,run方法仍然可以访问到正确的值。

       在Java中,Lambda表达式和匿名内部类都可以捕获外部作用域中的变量。对于JDK 1.8之前的版本,只能捕获被final修饰的局部变量或者实例变量。这是因为这些变量一旦初始化后就不能改变,所以它们可以在Lambda表达式或匿名内部类中使用而不会引发线程安全问题。

       然而,从JDK 1.8开始,Java引入了一个新的特性叫做"effectively final"。这个特性允许我们在Lambda表达式或匿名内部类中捕获那些实际上没有被修改过的变量。换句话说,即使变量没有被明确地声明为final,只要它在Lambda表达式或匿名内部类中没有被修改过,就可以被捕获。

4.实现自定义线程池

这里的实现自定义线程池比较简单,不多过于赘述。

class MyThreadPool {private BlockingQueue<Runnable> queue = new LinkedBlockingDeque<>();//n表示线程数量public MyThreadPool(int n) {//在这里创建线程for (int i = 0; i < n; i++) {Thread t = new Thread(() -> {while (true) {try {Runnable runnable = queue.take();runnable.run();} catch (InterruptedException e) {e.printStackTrace();}}});t.start();}}//注册任务给线程池public void submit(Runnable runnable) {try {queue.put(runnable);} catch (InterruptedException e) {e.printStackTrace();}}
}

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

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

相关文章

【学术会议征稿】第五届机械工程、智能制造与自动化技术国际学术会议(MEMAT 2024)

第五届机械工程、智能制造与自动化技术国际学术会议&#xff08;MEMAT 2024&#xff09; The 5th International Conference on Mechanical Engineering, Intelligent Manufacturing and Automation Technology 目前&#xff0c;我国自动化技术随着科学技术水平的不断提高已经…

功率器件和滤波器件的选型及测试方法

目录 一、功率器件的选型及测试方法 1.1功率器件的选型 1.2功率器件的测试方法 二、滤波器件的选型及测试方法 2.1滤波器件的选型 2.2滤波器件的测试方法 三、表格总结 一、功率器件的选型及测试方法 1.1功率器件的选型 在电子电路设计中&#xff0c;功率器件的选择是…

Mysql索引不当引发死锁问题

1. 前言 在并发量很低的情况下&#xff0c;mysql的响应时延一切正常&#xff0c;一旦并发量上去了&#xff0c;mysql就会出现死锁的情况&#xff0c;你有没有遇到过&#xff1f;到底是是什么原因导致的呢&#xff0c;让我们一起看看真实的案例。 2.遇到的问题 先介绍一下我们…

二进制、十进制转换进阶--小数点后的转换

上一篇文章详细介绍了整数的二进制,八进制,十进制,十六进制之间的转换 详情可前往:二进制、八进制、十进制、十六进制的相互转换-CSDN博客 这篇介绍含有小数点之间的转换 一:二进制转十进制 二进制 101.11 可以分为两部分 101 和 0.11 整数部分 101 转换的方式是从右到左,…

【文心智能体】通过低代码工作流编排创建应用《挑战奥运问答拿奖牌》

欢迎来到《小5讲堂》 这是《文心智能体平台》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 背景整体界面大模型链提示词模型 工具链HTTP请求工具 逻辑…

游戏开发设计模式之策略模式

目录 策略模式在游戏开发中的具体应用案例有哪些&#xff1f; 如何在Unity中实现策略模式以优化角色行为和AI策略&#xff1f; 策略模式与其他设计模式&#xff08;如观察者模式、状态模式&#xff09;在游戏开发中的比较优势是什么&#xff1f; 策略模式的优势 观察者模式…

【Qt笔记】QCommandLinkButton控件详解

目录 引言 一、概述 二、特性与属性 1. 属性 2. 样式 三、基本用法 1. 引入必要的头文件 2. 创建和配置 QCommandLinkButton 3. 布局管理 四、高级用法 1. 自定义绘制 2. 动态内容更新 五、代码解析示例 注意 总结 引言 QCommandLinkButton 是 Qt 框架中 QtWi…

android关于binder的简单通信过程

文章目录 简述aidl文件服务端的实现客户端的实现验证过程 简述 主要实现的是两个应用之间跨进程通信的过程&#xff0c;client端调用server端的具体实现&#xff0c;然后server端给client回调数据&#xff0c;详细如下所示 aidl文件 以下的文件需要在服务端与客户端都配置一…

外包干了两年,快要废了。。。

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 简单的说下&#xff0c;我大学的一个同学&#xff0c;毕业后我自己去了自研的公司&#xff0c;他去了外包&#xff0c;快两年了我薪资、技术各个方面都有了很大的…

Linux top 命令详解

top命令是Linux和Unix系统中一个非常强大的实时系统监控工具&#xff0c;它可以显示系统中各个进程的实时动态管理视图&#xff0c;类似于Windows的任务管理器。在需要诊断系统性能问题或监控资源使用情况时是非常有用的。 使用top命令 在命令行中输入top并回车&#xff0c;即…

Dubbo ZooKeeper Spring Boot整合

依赖配置 1. Dubbo 起步依赖 Dubbo 是一款高性能的 Java RPC 框架&#xff0c;用于快速开发高性能的服务。 <dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>${dubbo.ver…

非阻塞轮询

目录 前言1.options 参数2. 非阻塞轮询3. 模拟非阻塞轮询4. 非阻塞轮询 执行其它任务 前言 继上一篇文章 详谈进程等待 讲到 waitpid 系统调用&#xff0c;在该系统调用接口中还有一个 options 参数&#xff0c;本篇文章介绍 watipid 系统调用中的options 参数 以及 什么是非…

谈到这个痛点,写C的和不写C的码农都沉默了

声明&#xff1a;此篇为 ai123.cn 原创文章&#xff0c;转载请标明出处链接&#xff1a;https://ai123.cn/2246.html 作为一名在计算机软件行业工作的C工程师&#xff0c;我深知在高要求的内存管理环境中工作有多么艰难。内存分配与优化、避免内存泄漏&#xff0c;都是日常挑战…

工业相机测长仪的组成部分

关键字:工业相机测长仪,高精度测长仪,视觉测量系统,蓝鹏测控测长仪,工业测长仪, 本文介绍了蓝鹏测控公司机器视觉业务 测长仪的核心产品及技术特点&#xff0c;主要涵盖相机部分、相机防护系统、补光系统和软件部分。 &#xff08;一&#xff09;相机部分 我司的机器视觉业务…

SpringBoot 项目——抽奖系统

本项目主要实现的功能是&#xff1a;主要服务于管理员用户&#xff0c;其可圈选奖品&#xff0c;人员来创建抽奖活动&#xff0c;并进行在线抽奖&#xff0c;并可通过短信或邮件的方式通知中奖者&#xff0c;同时普通用户可查看已结束的抽奖活动的中奖结果&#xff1b; 一、项…

JAVA电子器件制造行业生产管理系统计算机毕设计算机毕业设计

项目开发意义 目前小型企业基本上是采用人工完成生产及物料的车间计划,由于企业运作是以订单驱动而非计划生产,人工手段无法及时随新订单的到来更新计划,造成计划偏离实际;各个生产单位(车间)各自为战,分别提出物料、设备、专用工具的需求,在整个企业层面上很难较精确地控制物料…

C++核心编程02——引用

摘录于B站黑马程序员提供的笔记。 1. 引用的基本使用 作用&#xff1a; 给变量起别名 语法&#xff1a; 数据类型 &别名 原名 实例&#xff1a; #include <iostream> using namespace std;int main() {// 引用基本语法// 数据类型 &别名 原名int a 10;in…

2024年8月28日(docker网络)

跨主机的容器网络连接 A>mysql B>java容器 将A -p3306:3306 端口映射就可以实现 一、docker网络 1、本地网络 bridge 所有容器连接到桥就可以使用外网,使用nat让容器可以访问外网,使用ip a s指令查看桥,所有容器连接到此桥,ip地址都是172.17.0.0/16网段,桥是启动…

ESP8266通过WiFiManager实现Web配网

背景 一个项目中使用到了一款压力传感器,需要通过单片机实现数据的采集并发送到远程的服务器上,单片机采用的时ESP8266,通过WiFiManager实现局域网配置,以及远端服务器IP地址和服务端口的配置。发布此文章记录一下使用WiFiManager实现配网的方法。 程序流程图 示例代码 …

【机器学习-监督学习】双线性模型

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈Python机器学习 ⌋ ⌋ ⌋ 机器学习是一门人工智能的分支学科&#xff0c;通过算法和模型让计算机从数据中学习&#xff0c;进行模型训练和优化&#xff0c;做出预测、分类和决策支持。Python成为机器学习的首选语言&#xff0c;…