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

【JavaEE初阶一】线程的概念与简单创建

1. 认识线程(Thread)

1.1 关于线程

1.1.1 线程是什么

        由前一节的内容可知,进程在进行频繁的创建和销毁的时候,开销比较大(主要体现在资源的申请和释放上),线程就是为了解决上述产生的问题而提出的方案;线程保持了独立调度执行,这样的“并发支持”,如此同时省去“分配资源”“释放资源”带来的额外开销。

        一个线程就是一个 "执行流". 每个线程之间都可以按照顺序执行自己的代码. 多个线程之间 "同时" 执行 着多份代码, 一个进程中可以并发多个线程,每条线程并行执行不同的任务。

1.1.2  为啥要有线程

1、首先, "并发编程" 成为 "刚需".

        单核 CPU 的发展遇到了瓶颈. 要想提高算力, 就需要多核 CPU. 而并发编程能更充分利用多核 CPU 资源. 有些任务场景需要 "等待 IO", 为了让等待 IO 的时间能够去做一些其他的工作, 也需要用到并发编 程.

2、其次, 虽然多进程也能实现 ,并发编程, 但是线程比进程更轻量.

        创建线程比创建进程更快.

        销毁线程比销毁进程更快.

        调度线程比调度进程更快.

3、最后, 线程虽然比进程轻量, 但是人们还不满足, 于是又有了 "线程池"(ThreadPool) 和 "协程" (Coroutine)

1.2 进程与线程

1.2.1 简单讲解

        下面来可能错误的分析一下进程与线程在创建和销毁的时候对内存地址的利用:

         下图我们用pcb来描述一个进程,图解如下:

        如上图所示,每一个进程在创建和销毁时都会在内存空间操作自己的地址,在进行多进程并发执行的时候,多个进程大规模的创建和销毁会再一定程度上消耗系统和操作系统的资源;

        下图我们来用pcb描述一下线程,图解如下图所示:

        pcb中有一个属性就是内存指针,如上图所示,多个线程的内存指针都指向内存地址中的同一个位置;

        这就意味着以上多个线程只有在第一个线程创建的时候需要从系统中分配资源,后序的线程就不需要继续在分配资源了,直接公用前面的那份资源就行了;

        同时除了内存之外,文件描述符(操作硬盘),也是多个线程共用一份的;当然我们也要注意不是所有的线程都能实现如上程度的资源共享的,只有我们设置的线程组才能实现资源共享;

        综上:线程的出现解决了频繁申请和释放资源的开销

 1.2.2 两者的关系

       没有进程的时候,进程扮演两个角色(资源分配的基本单位调度执行的基本单位

        引入了线程之后,进程只需要扮演一个角色(资源分配的基本单位),线程分担了一个角色的(调度执行的基本单位

        关于线程和进程的小结:

1、进程是包含线程的;

2、每一个线程也是一个独立的执行流,且可以执行一段代码,并且单独的参与到cpu调度中(状态,上下文,优先级,记账信息,每一个线程都有自己的一份)

3、每个进程有着自己独有的资源,进程中的线程公用这一份资源(内存空间和文件描述符)----->(进程是资源分配的基本单位,线程是调度执行的基本单位)

4、进程和进程之间,不会相互影响;如果一个进程的某个线程抛出异常,是可能会影响到其他线程的,由此会把整个进程中的所有线程都异常终止;

5、同一个进程中的线程之间,可能会相互干扰,从而引起线程安全问题;

6、当然线程不是越多越好,要能够合适,如果线程太多的话,调度开销就可能十分明显;

1.3 java线程和操作系统之间的关系

        线程是操作系统中的概念. 操作系统内核实现了线程这样的机制, 并且对用户层提供了一些 API 供用户使用(例如 Linux 的 pthread 库).

        Java 标准库中 Thread 类可以视为是对操作系统提供的 API 进行了进一步的抽象和封装.

        所谓多线程编程:

        写代码的时候可以使用多线程进行并发编程(在java中不太推荐,很多和多线程编程相关的api在java标准库中都没有提供),也可以使用多线程并发编程(系统提供了多线程编程的api,java的标准库把这些api封装了,如此在代码中就可以使用了

        由此可以得出多线程在并发编程的时候,效率更高(频繁创建销毁的时候),尤其是对于java进程,是要启动java虚拟机的,如果启动java虚拟机,则这个事情的开销更大,--->可类似的看成搞多个java进程就是多个java虚拟机。

2. 初识多线程程序

        首先要有一个注意的点:

  • 每个线程都是一个独立的执行流
  • 多个线程之间是 “并发” 执行的

2.1 详细代码

        代码一:通过代码详细了解thread类:

        Java中提供的api,是通过thread这样的类进行展开的。

package thread;// 1. 创建一个自己的类, 继承自这个 Thread
class MyThread extends Thread {@Overridepublic void run() {// run 方法就是该线程的入口方法.System.out.println("圣诞节快乐,委婉待续!!!");}
}public class ThreadDemo1 {public static void main(String[] args) {// 2. 根据刚才的类, 创建出示例. (线程实例化, 才是真正的线程).// MyThread t = new MyThread();Thread t = new MyThread();// 3. 调用 Thread 的 start 方法, 才会真正调用系统 api, 在系统内核中创建出线程.t.start();}
}

        结果如下:

        代码二:编写mythread自定义类线程,在主线程中运行该自定义线程,代码如下:

package thread;
//1、创建一个自己的类,继承自这个thresd
class MyThread2 extends Thread{//重写run方法@Overridepublic void run() {//run 方法就是该线程的入口方法while (true){System.out.println("hello thread,委婉待续");try {Thread.sleep(1000);//休眠1000ms} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}
public class ThreadDemo2 {//创建一个main方法public static void main(String[] args){//2、根据刚才的类,创建出实例(线程实例,才是整整的线程)MyThread2 t = new MyThread2();//3、调用thread的start方法,才会整整的调用系统的api,在系统的内核中创建出线程池,//然后线程就开始运行我们的run方法中的代码t.start();while (true){System.out.println("hello main,smallye");try {Thread.sleep(1000);//休眠1000ms} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}

        结果显示:

 

        结果显示交替进行,这就展现出了多线程与普通程序的区别

 2.2 代码深入分析:

2.2.1 一些问答

Q1:关于上图Thread类为啥能直接使用,而不需要进行导包?

A1:在java标准库中,有一个特殊的包,java.lang(这个包时默认被导的,这里面的类默认使用)

Q2:为啥我们自定义类mythread2前面没有public?可以加public吗?

A2:不能,一个.java文件中,只能有一个public的类,这个mythread类没有被public修饰,就是只能在当前包里被其他的类使用。

Q3:讲解一下run方法与main方法的区别?

A3:上图就类似于main方法,该run方法是一个java进程(程序)的入口方法(一般将“跑起来”的程序称为进程,没有运行起来的程序(.exe),称为“可执行文件”),且此处的run方法,不需要手动调用,会在合适的时候(此时是线程创建好了之后,即被实例化后),被jvm自动调用执行。(如此风格的函数,称为“回调函数callback”)

Q4:以上字符代表的含义?关于方法重写的含义?

A4:

1、首先上图字符是方法重写的注解,主要目的就是方便让编译器检查我们的代码是否构成方法重写(语法中有很多机制,就是让编译器对我们的代码进行检查,如果我们明确该方法是重写的,有了这个注解编译器就会检查我们的方法是否满足方法的重写,参数等是否满足方法重写的要求,这样就能够及时的报错,大大的提高了我们的工作效率)

2、方法重写:就是让你能够对现有的类,进行扩展,写出符合场景需求的具体方法。

我们写的以上线程,肯定是让这个线程执行一些代码的。Thread类本身就会带有一个人入口方法,但是很明显标准库自带的run是不知道我们的需求业务是啥样的,所以我们必须要手动指定(即写出一个具体的业务),这样就需要针对原有的Thread进行扩展,Thread会有很多属性方法,大部分内容复用即可,只要把需要扩展的内容进行扩展即可。

Q5:thread.sleep的作用?

A5:所谓sleep是java中封装后版本中thread中提供的静态方法,其主要作用就是让当前的线程进行休眠,时间单位是ms;

        当然sleep会出现java.lang.interruptedException异常,该异常出现的原因是我们要求休眠1000ms的线程会由于其他原因导致提前被唤醒,不能够休眠1000ms

Q5.1:下图中两个线程中的sleep为什么只有前者可以进行try-catch捕捉,而后者既可以进行try-catch捕捉,也可以进行抛出方法签名?

A5.1:正常情况下,一般受查异常既可以添加异常方法签名也可以使用try-catch捕捉;但是我们的前者sleep所在的mythread类中的run方法是要经过重写操作是具体实现的方法,如果我们添加了方法签名,那么由于语法所致,会让我们的方法不能构成重写操作;更有父类thread的run没有throws异常,所以子类重写的时候也不能有throws异常;

 2.2.2 多线程的运行逻辑

        如上图所示:

        在main方法中,主线程调用start方法(创建了t线程),此时cpu的两个核心开始运转,兵分两路,一方面执行沿着mian方法继续执行,即打印“hello main,smallye”;另外一方面,内核就通过刚才主线程api构造出t线程,并且执行run方法,即打印“hell0 thread,委婉待续”;同时这两个线程在同时执行的时候各论各的,互不干扰。

        但是正因为这样,所以考虑两个线程的执行顺序是一样的吗?

        其实这两个线程的执行顺序是不一样的,因为在操作系统的内核中,有“调度器”模块,该模块实现的方式是一种类似于“随机调度的”效果;

        所谓随机调度会导致以下两个后果:

        1、一个线程,被调到cpu上执行的时机是不确定的;

        2、上位到cpu里被执行的线程从cpu上下来的给别的线程上位的时机也是不确定的,如此就会导致线程“抢占式执行”,且当前的主流操作系统都是抢占式执行的;

        由于此案成创建本身是有开销的,故此在该开销本身的影响下,导致“hello main,smallye”会比“hell0 thread,委婉待续”快一点(大概率,但是不一定),综合题前所学,进程创建第一线程的时候开销是最大的,剩下的线程的开销都计较少;

2.3 使用 jconsole 命令观察线程

        我们可以使用jdk自带的工具 jconsole查看当前Java进程中所有的线程

        操作流程如下:

1、第一步,找到jdk

2、第二步,点进去,找到里面的bin文件点进去

3、第三步,点击bin文件夹里面的jconsole

4、第四步,找到你所创建进程

5、第五步,直接点击不安全连接就好

6、第六步,点击线程进行查看

        我们的t是指线程的变量名,所谓的看到的thread—0,是我们自定义线程的默认名字,一般会从0~n;

ps:本次的内容就到这里了,如果感兴趣的话就请一键三连哦!!!

        

相关文章:

【JavaEE初阶一】线程的概念与简单创建

1. 认识线程(Thread) 1.1 关于线程 1.1.1 线程是什么 由前一节的内容可知,进程在进行频繁的创建和销毁的时候,开销比较大(主要体现在资源的申请和释放上),线程就是为了解决上述产生的问题而提…...

三叠云工程劳务管理,优化建筑施工管理,提升效率与质量

随着建筑行业的蓬勃发展,工程施工现场管理变得愈发复杂。传统的人员管理方式已经无法满足企业快速发展的需求。如何提高施工效率、优化人力资源管理成为了建筑企业亟待解决的问题。逐渐走向数字化的工程建设行业,急需一种足以匹配这一时代变革、高效管理…...

RocketMQ连接报错RemotingConnectException: connect to <192.168.57.129:9876>解决

文章目录 前言一、RocketMQ 连接报错处理1.1 报错信息1.2 修改 broker.conf 文件1.3 Linux 开放端口1.4 项目启动成功 前言 上一篇文章:基于SpringBoot整合RocketMQ异步发送短信功能在项目启动的过程中报了 RocketMQ 连接错误。针对这个问题,本文给予记…...

设计模式--桥接模式

实验9:桥接模式 本次实验属于模仿型实验,通过本次实验学生将掌握以下内容: 1、理解桥接模式的动机,掌握该模式的结构; 2、能够利用桥接模式解决实际问题。 [实验任务]:两个维度的桥接模式 用桥接模式…...

redis基本用法学习(C#调用StackExchange.Redis操作redis)

StackExchange.Redis是基于C#的高性能通用redis操作客户端,也属于常用的redis客户端之一,本文学习其基本用法。   新建Winform项目,在Nuget包管理器中搜索并安装StackExchange.Redis,如下图所示:   StackExchange.…...

单挑力扣(LeetCode)SQL题:1308. 不同性别每日分数总计

相信很多学习SQL的小伙伴都面临这样的困境,学习完书本上的SQL基础知识后,一方面想测试下自己的水平;另一方面想进一步提升,却不知道方法。 其实,对于技能型知识,我的观点一贯都是:多练习、多实…...

Vue3组合式-依赖注入provideinject

一、注意点 专门强调了是3.0且是组合式,不是2.0不支持也不是选项式不支持provide&&inject,是支持但是有很明显的弊端,不建议使用 二、场景 官方的解释: 通常情况下,当我们需要从父组件向子组件传递数据时,会…...

SRE 与 DevOps 的不同之处

尽管网站可靠性工程 (SRE) 理念早在 2003 年就由 Google 的 Ben Treynor Sloss 提出,但其近年来却一直受到追捧。随着 DevOps 实践已经在许多组织中牢固确立,两者之间的冲突是否已经显现?SRE 只不过是一种过时的趋势吗?是 SRE 补充…...

【湖仓一体尝试】MYSQL和HIVE数据联合查询

爬了两天大大小小的一堆坑,今天把一个简单的单机环境的流程走通了,记录一笔。 先来个完工环境照: mysqlhadoophiveflinkicebergtrino 得益于IBM OPENJ9的优化,完全启动后的内存占用: 1)执行联合查询后的…...

SpringCloud跨服务调用失败Seata无法回滚解决办法

遇到的问题 在微服务项目中 有A、B、C三个服务 其中 A调用B服务 ,B调用C, 这些就是跨服务调用了,在A服务中 还调用了一个当前模块执行插入数据的方法(在这里我就叫它为AA 也就是mybatis/spring管理的本地事务) A服务开启全局事务注解 Globa…...

OSG三维渲染引擎编程学习之一百零一:“第十一章:OSG粒子” 之 “11.2 粒子模拟过程”

目录 第十一章 OSG粒子 11.2 粒子模拟过程 第十一章 OSG粒子 虚拟现实中有很多效果,如雨效、雪效、雾效等,这些都可以通过粒子条统来实现。一个真实的粒子系统的模式能使三维场景达到更好的效果。 粒子系统是一个非常复杂的粒子模拟过程。在OSG中,专门定义了新的名字空间o…...

Autosar CAN开发03(从实际应用认识CAN总线的物理层)

建议同时阅读本专栏的: Autosar CAN开发03(从实际应用认识CAN总线的物理层) Autosar CAN开发04(从实际应用认识CAN报文) Autosar CAN开发05(从实际应用认识CAN波特率) 前言 在上一章的《AU…...

vue中父子组件传值

父传子 传: 在"标签"上传属性 <Card :name"name"></Card> 接: 在props中 export default {props: {name: String},setup(props) {console.log(props.name);} } 子传父 传: 触发,给一个事件传值 setup(props,{emit}) {emit("get…...

【网络编程】基于UDP数据报实现回显服务器/客户端程序

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【网络编程】【Java系列】 本专栏旨在分享学习网络编程的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 前言 我们如果…...

sqlilabs第三十二三十三关

Less-32&#xff08;GET - Bypass custom filter adding slashes to dangerous chars) 手工注入 由 宽字符注入可知payload 成功触发报错 http://192.168.21.149/Less-32/ ?id1%df 要写字符串的话直接吧字符串变成ascii码 注意16进制的表示方式 自动注入 sqlmap -u http:…...

第二十一章博客

计算机应用实现了多台计算机间的互联&#xff0c;使得它们彼此之间能够进行数据交流。网络应用程序就是在已连接的不同计算机上运行的程序&#xff0c;这些程序借助于网络协议&#xff0c;相互之间可以交换数据。编写网络应用程序前&#xff0c;首先必须明确所要使用的网络协议…...

PSoc62™开发板之按键控制LED

实验目的 使用板子上的用户自定义按键控制LED亮灭&#xff0c;当按键按下时LED亮起来&#xff0c;不按下则不亮 电路图 按键电路 板子有两组按键&#xff0c;分别是系统复位按键和用户自定义按键&#xff0c;这里我们选择控制用户自定义按键&#xff0c;可以看到MCU_USER_B…...

Vue-Pinina基本教程

前言 官网地址&#xff1a;Pinia | The intuitive store for Vue.js (vuejs.org) 看以下内容&#xff0c;需要有vuex的基础&#xff0c;下面很多概念会直接省略&#xff0c;比如state、actions、getters用处含义等 1、什么是Pinina Pinia 是 Vue 的存储库&#xff0c;它允许您跨…...

大批量数据导出csv,平替导出excel性能优化解决方案封装工具类

阿丹&#xff1a; 有些业务逻辑需要在导出非常大量的数据&#xff0c;几百甚至几千万的数据这个时候再导出excel来对于性能都不是很友好&#xff0c;这个时候就需要替换实现思路来解决这个问题。 本文章提供了两种解决的方案&#xff0c;也是两种从数据库中拿取数据的方式一种是…...

C++ Qt开发:Charts绘制各类图表详解

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍TreeWidget与QCharts的常用方法及灵活运用。 …...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...