【后端开发】JavaEE初阶—线程的理解和编程实现
前言:
🌟🌟本期讲解多线程的知识哟~~~,希望能帮到屏幕前的你。
🌈上期博客在这里:【后端开发】JavaEE初阶——计算机是如何工作的???-CSDN博客
🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客
目录
📚️1.引言
📚️2.线程内部原理
2.1线程的作用
2.2线程和进程的区别
2.3线程的缺点
1.引入更多的线程
2.线程冲突
2.4 线程原理总结
📚️3.多线程编程
3.1代码实现
3.2两个线程执行
3.3线程创建的方式
1.直接继承Thread并重写run方法
2.实现Runnable接口,重写run方法
3.继承Thread,重写run并使用匿名内部类
4.实现Runnable,重写run,使用匿名内部类
5.lambda表达式
📚️5.总结
📚️1.引言
Hello!!!家人们,小编又回来啦,上期讲解了关于计算机中的重要知识进程,后面我们讲到进程在频繁的申请和销毁时会造成系统开销很大,那么就要引入线程了,接下来本期就开始讲解关于后端开发的重要知识“多线程”,开始发车了。加油加油~~~🥳🥳🥳
且听小编讲解,包你学会!!!
📚️2.线程内部原理
2.1线程的作用
线程:线程可以看做是轻量化的进程
注意:线程既可以保持独立调度执行,满足了并发执行,并且省去了分配资源和释放资源带来的额外开销;这就使得线程较好的弥补了进程的缺点
2.2线程和进程的区别
前面用PCB来描述进程,本期用PCB来表示线程
操作系统对于“多任务的调度”本质上是对PCB进程的调度,而线程和进程属性基本一致,都有状态,优先级,记账信息等;
这两者的较大区别:
此时可以看到:每个进程要申请一个内存空间,而每一个线程都共用一个内存空间;
注意:此时就有一个重要的属性概念:内存指针,多线程的PCB的内存指针指向的是同一个内存地址;那么在第一个线程申请了分配资过后,后面创建的线程就不用分配资源了,直接省去了资源分配带来的系统消耗;
当然除了内存空间,还有文件描述附表(操作硬盘)这也是多线程共用的;
注意:能够把资源共享的线程,分成一组叫做线程组,线程组是进程的一部分
图例如下:
注意:
在没有线程之前,进程既是分配资源的基本单位,也是调度执行的基本单位。
线程存在后,进程是资源分配的基本单位,线程是调度执行的基本单位;
对于两者有啥意义上的区别:
假如有一个桌子上有40个水果,要把这个水果吃完,就有两种方式
第一种:
第二种:
此时就能够发现:第一种模拟的是进程的方法,第二种模拟的是线程的方法,那么就可以发现:进程种方法在并发执行任务时会不断分配资源(就是房间),线程执行的时候,就公用一个内存空间(公用一个房间),就不会重新分配新资源;
2.3线程的缺点
1.引入更多的线程
图例如下:
此时可以看到,当我们引入更多的线程之后,他们之间会相互竞争,会造成拥挤(即抢占去吃苹果),这就会造成,引入过多的线程后,执行效率反而不高了;
结果:当线程有太多的时候,线程会相互竞争CPU资源了(CPU的核心数量是有限的),这样不但不会提升执行效率,还会增加系统调度的开销;
2.线程冲突
假如线程1和线程二看上了同一块苹果,那么就会存在两个线程之间的冲突,苹果是谁的,也不确定
结果:线程冲突,会导致代码出现逻辑上的错误即线程安全问题;
2.4 线程原理总结
1.每个线程都是一个独立的执行流,都可以单独参与到CPU的调度中去
2.每个进程都有自己的资源,进程中的线程共用这一份资源
3.进程和进程之间不会相互影响,但是进程中的线程之间,当一个线程抛出异常,其他线程会受到影响,导致整个线程异常终止
4同一个进程内的线程之间会相互影响,导致线程安全问题
5.线程不是越多越好,太多了会导致系统调度开销增大
📚️3.多线程编程
在写代码的时候可以用多进程编程,和多线程编程;但是在Java库中对应的多进程编程是没有对应API的,并且前面也讲到多线程编程在资源分配上优于多进程编程,所以就用多线程编程;
3.1代码实现
首先创建一个类去继承Thread类,这里的Thread类是由java.lang包里的,并要重写run()方法,这个方法即是线程的入口,代码如下:
class mythread extends Thread{//重写run方法,该线程的入口方法@Overridepublic void run(){}}
}
注意事项;
1.这里的方法不用调用,当线程创建好之后,JVM会自动帮我们进行调用;
2.每个进程中都有至少有一个线程,进程中的第一个线程就是主线程,所以我们的main方法就是主线程的入口;
3.Thread类本身会有一个run()方法
创建实例,调用start方法,这样才会在系统内核中创建真正的线程,代码如下:
public static void main(String[] args) {//构造实例mythread t=new mythread();//Thread t=new Thread();t.start();
注意:
在实例化对象时,可以直接用mythread类,但是也可以使用Thread来接收,这就是完成了一个向上转型
这里如果直接new一个Thread的对象后,创建线程后,JVM会自动调用这个类本身的run()
我们这里简单演示一下,线程的代码和结果;
public class threadDeom1 {public static void main(String[] args) {//构造实例//mythread t=new mythread();Thread t=new mythread();t.start();}
}
//写一个类继承thrad
class mythread extends Thread{//重写run方法,该线程的入口方法@Overridepublic void run(){while (true){System.out.println("这是thread线程");//防止打印过快try {Thread.sleep(1000);}catch (InterruptedException e){throw new RuntimeException();//抛出异常}}}
}
注意:这里的Sleep是线程休眠的意思,1000代表的ms所以这里就是一秒,并且此时还要抛出异常,程序才能正常执行;
结果:
此时这张图只是一部分,线程会不断执行,这里小编只是截取了一小部分;
3.2两个线程执行
这里的代码如下:
public static void main(String[] args) {//构造实例//mythread t=new mythread();Thread t=new mythread();t.start();while (true){System.out.println("这是main线程");try {Thread.sleep(1000);}catch (InterruptedException e){throw new RuntimeException();}}}
}
//写一个类继承thrad
class mythread extends Thread{//重写run方法,该线程的入口方法@Overridepublic void run(){while (true){System.out.println("这是thread线程");//防止打印过快try {Thread.sleep(1000);}catch (InterruptedException e){throw new RuntimeException();//抛出异常}}}
这里存在两个死循环,但是这两个输出语句仍然进行了打印,这是为什么呢???
注意:线程是两个独立的执行流,所以此处在调用start方法后,线程就有两种,一路继续沿着main方法、即主线程,另一种就是进入线程的run方法;
这里的打印顺序是不确定的,因为操作系统内核中有“调度器这一模块”,即一种随机调度的效果
随机调度:
一个线程什么时候被CPU调度是不确定的;
一个线程什么时候从CPU上下来,给其他线程让位也是不确定的;
上述代码输出结果:
这里大家可以多次实验一下,可以看到为第一个输出的总是main线程呢???
注意:当使用start方法后,主线程会直接向下执行,但是操作系统的内核就要根据刚才的api创建出线程来,并执行run方法;又因为创建线程也有开销(比进程小很多,但是不为0),所以会导致主线程更快;
3.3线程创建的方式
1.直接继承Thread并重写run方法
代码实现:
public static void main(String[] args) {//构造实例//mythread t=new mythread();Thread t=new mythread();t.start();}
}
//写一个类继承thrad
class mythread extends Thread{//重写run方法,该线程的入口方法@Overridepublic void run(){}
注意:重写为了特定功能的展开,满足我们特定的需求;
2.实现Runnable接口,重写run方法
代码实现如下:
public static void main(String[] args) {Runnable runnable=new mythread1();//实现runnable接口Thread t=new Thread(runnable);t.start();//第二种写法Thread t=new Thread(new mythread1());t.start();//第三种写法mythread1 mythread1=new mythread1();Thread t=new Thread(mythread1);t.start();}
}
class mythread1 implements Runnable{@Overridepublic void run() {}
注意:小编这里介绍了三种写法,其实本质都是一样的,都是输入线程对象,并且在实例化对象时,一个使用了向上转型,还有一个没有使用向上转型而已;
3.继承Thread,重写run并使用匿名内部类
代码实现如下:
public static void main(String[] args) {Thread t=new Thread(){public void run(){}};t.start();while (true){System.out.println("这是main线程");try {Thread.sleep(1000);}catch (InterruptedException e){throw new RuntimeException();}}}
注意:{}中可以主要是定义子类的属性和方法,这里最主要还是进行run方法的重写;下面的死循环是为了方便进行两种线程存在执行情况;
4.实现Runnable,重写run,使用匿名内部类
代码实现如下:
public static void main(String[] args) {Thread t=new Thread(new Runnable() {@Overridepublic void run() {}});t.start();while (true){System.out.println("这是mian线程");try {Thread.sleep(1000);}catch (InterruptedException e){throw new RuntimeException();}}}
注意:这里Thread括号里使用的参数,是Runnable接口匿名内部类的实例,这个就像是之前在lambda表达式中,比较器的写法,这里大家可以参考一下:【数据结构】Lambda表达式的应用-CSDN博客
5.lambda表达式
代码如下:
public static void main(String[] args) {//lambda表达式Thread t=new Thread(()->{while (true){}});t.start();while (true){System.out.println("这是main线程");try {Thread.sleep(1000);}catch (InterruptedException e){throw new RuntimeException();}}}
注意:这里的lambda表达式中()内没有参数,其实这就是实现Runnable接口匿名内部类的一种写法,由于只有一个方法,且参数为空,所以这个括号内也就是空,并且后面的方法体就是重写run()方法;
📚️5.总结
💬💬小编本期讲解了JavaEE初阶的重要知识线程,以及和进程之间的关系,以及线程的优点和缺点,并且讲述了在编程中线程的实现,以及线程的创建的五种方式,还附上了代码供小伙伴参考参考~~~
代码上传Gitee啦:朱海洋/Thread (gitee.com)
🌅🌅🌅~~~~最后希望与诸君共勉,共同进步!!!
💪💪💪以上就是本期内容了, 感兴趣的话,就关注小编吧。
😊😊 期待你的关注~~~
相关文章:

【后端开发】JavaEE初阶—线程的理解和编程实现
前言: 🌟🌟本期讲解多线程的知识哟~~~,希望能帮到屏幕前的你。 🌈上期博客在这里:【后端开发】JavaEE初阶——计算机是如何工作的???-CSDN博客 🌈感兴趣的小伙…...

Matlab simulink建模与仿真 第十九章(生成C代码)
一、Configuration Parameters模型参数配置 1、仿真时间 (1)在Solver选项卡中可以设置仿真的起始时间和结束时间,一般起始时间设为0,而结束时间按需设置。 (2)如果希望仿真不会自动暂停(也就…...

遍历9个格子winmine!StepBlock和遍历8个格子winmine!StepBox的对决
遍历9个格子winmine!StepBlock和遍历8个格子winmine!StepBox的对决 第一部分:windbg调试记录。 0: kd> g Breakpoint 10 hit winmine!DoButton1Up: 001b:0100390e a130510001 mov eax,dword ptr [winmine!xCur (01005130)] 0: kd> kc # 00 winmine…...

Python中的文件编码:揭开字符世界的神秘面纱
引言 在计算机系统中,数据是以二进制形式存储的。而我们日常见到的文字、符号等信息,则需要通过特定的方式转化为二进制数据,这就是编码的过程。不同的编码方式决定了如何将字符映射成字节序列。选择合适的编码方案不仅能够保证信息传输的准…...

Vue3使用hiprint——批次打印条码
例图:打印编号 一、安装Vue-Plugin-HiPrint 要开始使用 Vue-Plugin-HiPrint,首先需要安装它。可以使用 npm npm install vue-plugin-hiprint --save 二、在main.js中引入 Vue-Plugin-HiPrint 在您的 main.js 或任何其他入口文件中,您可以按…...

智慧城市主要运营模式分析
(一)运营模式演变 作为新一代信息化技术落地应用的新事物,智慧城市在建设模式方面借鉴了大量工程建设的经验,如平行发包(DBB,Design-Bid-Build)、EPC工程总承包、PPP等模式等,这些模式在不同的发展阶段和条件下发挥了重要作用。 在智慧城市发展模式从政府主导、以建为主、…...

典型的MVC设计模式:使用JSP和JavaBean相结合的方式来动态生成网页内容典型的MVC设计模式
先看代码与实现: 文件结构 triangle_area4.jsp <% page contentType"text/html;charsetUTF-8" pageEncoding"UTF-8" %> <html> <body> <%--<jsp:useBean>:用于在JSP中实例化JavaBean。在这里,…...

Vue引入js脚本问题记录(附解决办法)
目录 一、需求 二、import引入问题记录 三、解决方式 一、需求 我想在我的Vue项目中引入jquery.js和bootstrap.js这种脚本文件,但发现不能单纯的import引入,问题如下。 二、import引入问题记录 我直接这么引入,发现控制台报错TypeError: …...

数据清洗与数据治理的关系
数据清洗与数据治理是数据处理过程中的两个重要步骤,它们共同确保数据的质量和可靠性,以便于数据分析和决策支持。 数据清洗 数据清洗(Data Cleaning)是指识别并纠正或删除数据集中的不准确、不完整、重复或错误的记录的过程。数…...

树莓派pico上手
0 介绍 不同于作为单板计算机的树莓派5,树莓派 pico 是一款低成本、高性能的微控制器板,具有灵活的数字接口。主要功能包括: 英国树莓派公司设计的 RP2040 微控制器芯片双核 Arm Cortex M0 处理器,弹性的时钟频率高达 133 MHz26…...

TypeError: load() missing 1 required positional argument: ‘Loader‘
标题TypeError: load() missing 1 required positional argument: ‘Loader’ 源码: 处理后: 顺利通过,由于yaml版本导致的问题...
根据软件架构设计与评估的叙述开发一套机器学习应用开发平台
案例 阅读以下关于软件架构设计与评估的叙述,回答问题 1和问题 2。 【说明】 某公司拟开发一套机器学习应用开发平台,支持用户使用浏览器在线进行基于机器学习的智能应用开发活动。该平台的核心应用场景是用户通过拖拽算法组件灵活定义机器学习流程&…...

【隐私计算篇】利用多方安全计算MPC实现VGG16人脸识别隐私推理
1. 背景介绍 本文主要介绍一种利用多方安全计算MPC技术,实现VGG16的人脸识别模型,侧重于模型推理阶段,目前已经公开专利,因此以下内容的分享都是基于公开材料。该分享涉及到最小化多方安全计算(MPC)以及明密文混合计算的思想&…...

Python 入门教程(3)基础知识 | 3.7、pass 关键字
文章目录 一、pass 关键字1、定义与用法2、pass 关键字的用法2.1、函数定义中的占位符2.2、 类定义中的占位符2.3、条件语句中的占位符2.4、循环中的占位符 3、注意事项 一、pass 关键字 1、定义与用法 pass语句用作将来代码的占位符。当执行pass语句时,不会有任何…...

nodejs基于vue+express度假村旅游管理系统设计与实现7t82p
目录 功能介绍数据库设计具体实现截图技术栈技术论证解决的思路论文目录核心代码风格详细视频演示源码获取 功能介绍 实现了一个完整的农家乐系统,其中主要有用户表模块、关于我们模块、收藏表模块、公告信息模块、酒店预订模块、酒店信息模块、景区信息模块、景区…...

【裸机装机系列】16.kali(ubuntu)-安装linux和win双系统-重装win11步骤
推荐阅读: 1.kali(ubuntu)-为什么弃用ubuntu,而选择基于debian的kali操作系统 注意: 要先装windows,再装linux,不然linux的启动分区会被覆盖掉。为什么双系统要先装windows呢? 在一个新硬盘上࿰…...

基于TypeScript+React+AntDesign 的车辆车型管理页面
项目目录结构: my-app/├── node_modules/├── public/├── src/│ ├── App.js│ ├── VehicleForm.js│ └── index.js├── package.json└── README.md目录 1.创建项目 2.列表页面VehicleForm.js,预留接口使用axios 1.创建项目 npx crea…...

sentinel-dashboard数据 redis 持久化
概述 随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来…...

【C++】——vector深度剖析模拟实现
低头赶路,敬事如仪 目录 1、模拟vector 1.1底层结构 1.2构造析构 1.3尾插扩容 1.4迭代器 1.5增删查改 1.6模拟中的注意事项 2、vector模拟补充 2.1迭代器区间构造问题 2.2memcpy深浅拷贝问题 2.3动态二维数组的模拟及遍历 1、模拟vector 想要模拟实现自…...

OpenCV特征检测(11)从一组点中检测直线的函数
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在一组点中使用标准霍夫变换查找直线。 该函数使用霍夫变换的一种改进方法在一组点中查找直线。 HoughLinesPointSet 是 OpenCV 中的一个函数&a…...

C++_24_适配器
A 函数对象 概念: 重载函数调用运算符的类实例化的对象,就叫函数对象.又名仿函数,函数对象和()触发重载函数调用运算符的执行。 作用: 为算法提供策略 示例: #include <iostream> using namespace s…...

算法.图论-并查集
文章目录 1. 并查集介绍2. 并查集的实现2.1 实现逻辑2.2 isSameSet方法2.3 union方法(小挂大优化)2.4 find方法(路径压缩优化) 3. 并查集模板4. 并查集习题4.1 情侣牵手4.2 相似字符串组 1. 并查集介绍 定义: 并查集是一种树型的数据结构,用于处理一些不…...

elasticSearch常见命令及历史数据迁移
es这种非关系型数据库,感觉可视化效果不是很好,个人在操作中,习惯性通过简单的方式去访问。也是接触不久。只能出一些基操。共同学习记录,大家有好的操作也可留言备注。 1,常见命令 1)查询有哪些index&…...

WebLogic 漏洞复现
1、后台弱⼝令GetShell 默认账号密码:weblogic/Oracle123 weblogic常⽤弱⼝令:https://cirt.net/passwords?criteriaweblogic 这⾥注意, 单个账号错误密码5次之后就会⾃动锁定。 http://47.121.212.195:7001/console 2、登录后台后&#…...

web基础:域名、网页、HTML、web版本
文章目录 引言域名网站访问方式域名结构域名解析DNS解析过程 网页网页文件类型静态网页与动态网页常用动态网页编程语言 HTMLHTML 语法规则HTML 文件结构HTML 文件基本结构示例:常用 HTML 标签HTML文件基本结构 WEB版本 引言 web(World Wide Web&#x…...

【项目案例】物联网比较好的10+练手项目推荐,附项目文档/源码/视频
练手项目推荐 1 智能小车 项目功能介绍: 本项目由三部分组成:应用端(微信小程序)、设备端(Hi3861)、驱动端(UPS)。 1. 应用端,采用微信小程序作为应用端控制界面。在开…...

AWS注册时常见错误处理
引言 创建AWS账号是使用AWS云服务的第一步,但在注册过程中可能会遇到一些常见的问题。本文中九河云将帮助您排查和解决在创建AWS账户时可能遇到的一些常见问题,包括未接到验证电话、最大失败尝试次数错误以及账户激活延迟等。 常见问题及解决方法 1. …...

Spark-RDD持久化
一、Spark的三种持久化机制 1、cache 它是persist的一种简化方式,作用是将RDD缓存到内存中,以便后续快速访问,提高计算效率。cache操作是懒执行的,即执行action算子时才会触发。 2、persist 它提供了不同的存储级别࿰…...

vue2中使用tailwindCss 详细教程
1、先看官方文档:https://www.tailwindcss.cn/ 2、先安装:npm install -D tailwindcss ---------------通过 npm 安装 tailwindcss,然后创建你自己的 create your tailwind.config.js 配置文件。 npm install -D tailwindcss 3、初始化文件—npx tailwindcss init npx ta…...

机器视觉工程师一直做调试,维护岗位,想转岗软件方面C#从零开始,快则三年不到,慢则一辈子不会
其实不是每一家做视觉检测,或者是做设备必须要机器视觉工程师开发,其实公司对标准软件更感兴趣,主要非常高的性价比,省时省钱省人。所以这里有个问题,就是公司平台的重要性,首先他对开发是刚需,…...