【JavaEE初阶】线程的概念及创建
目录
📕 前言
📕 认识线程(Thread)
🚩 概念
😊线程是什么
🙂 为啥要有线程
😭 进程和线程的区别(面试题重点)
🤭 Java的线程和操作系统线程的关系
🚩 第⼀个多线程程序
🙂 使用 jconsole 命令观察线程
📕 创建线程
🚩方法一:继承 Thread 类
🚩 方法2:实现 Runnable 接口
🚩方法3:其他变形
📕 前言
当前的CPU都是多核心CPU,需要通过一些特定的编程技巧,把要完成的任务,拆解成多个部分,并且分别让他们在不同的cpu上运行,否则多核心cpu就形同虚设了,把这种编程称为"并发编程",代指了并行 + 并发。
📕 认识线程(Thread)
线程thread,也成为"轻量级进程",创建销毁开销更小
🚩 概念
😊线程是什么
一个线程就是一个 “执行流”. 每个线程之间都可以按照顺序执行自己的代码. 多个线程之间 “同时” 执行着多份代码
例如:
一家公司要去银行办理业务,既要进行财务转账,又要进行福利发放,还得进行缴社保。
如果只有张三一个会计就会忙不过来,耗费的时间特别长。为了让业务更快的办理好,张三又找来两位同事李四、王五一起来帮助他,三个人分别负责一个事情,分别申请一个号码进行排队,自此就有了三个执行流共同完成任务,但本质上他们都是为了办理一家公司的业务。
此时,我们就把这种情况称为多线程,将一个大任务分解成不同小任务,交给不同执行流就分别排队执行。其中李四、王五都是张三叫来的,所以张三一般被称为主线程(Main Thread)
结论:
线程是系统调度执行的基本单位!!!
进程是系统资源分配的基本单位!!!
所有上节课谈到的"进程调度"一系列内容,更准确的说都是"线程调度".
上节课谈到的可视为都是"只包含一个线程的进程"
🙂 为啥要有线程
首先, “并发编程” 成为 “刚需”
- 单核 CPU 的发展遇到了瓶颈. 要想提高算力, 就需要多核 CPU. 而并发编程能更充分利用多核 CPU
资源. - 有些任务场景需要 “等待 IO”, 为了让等待 IO 的时间能够去做一些其他的工作, 也需要用到并发编程
其次, 虽然多进程也能实现 并发编程, 但是线程比进程更轻量
- 创建线程比创建进程更快.
- 销毁线程比销毁进程更快.
- 调度线程比调度进程更快.
最后, 线程虽然比进程轻量, 但是人们还不满足, 于是又有了 “线程池”(ThreadPool) 和 “协程”(Coroutine)
关于线程池和协程博主会在后面一一介绍.此处暂时不做过多讨论
😭 进程和线程的区别(面试题重点)
例子:有一个滑稽老铁,他的任务是把100只鸡吃掉,如何一个滑稽在这吃,效率很低!!!
- 进程是包含线程的. 每个进程至少有一个线程存在,即主线程。
- 进程和进程之间不共享内存空间. 同一个进程的线程之间共享同一个内存空间.
- 进程是系统分配资源的最小单位,线程是系统调度的最小单位
🤭 Java的线程和操作系统线程的关系
线程是操作系统中的概念. 操作系统内核实现了线程这样的机制, 并且对用户层提供了一些 API 供用户使用(例如 Linux 的 pthread 库).
Java 标准库中 Thread 类可以视为是对操作系统提供的 API 进行了进一步的抽象和封装
🚩 第⼀个多线程程序
线程本身是由操作系统提供的,操作系统提供了API让我们操作线程,JVM就对操作系统的API进行了封装,线程这里,提供了 Thread 类来表示线程。
首先并不是直接在这里创建一个实例
而是写一个类,让这个类继承 Thread 类
然后在 myThread 类里面重写run方法,run方法的作用是用于描述线程具体干什么活!!!
在main方法中,创建myThread实例,通过对象的引用去调用start,就可以调用myTread里面的run
上述代码中,其实有两个线程!!!
1,一个是自己写的 t 线程,
2,一个是main方法所在的线程,是jvm进程在启动的时候,自己创建的线程(也就是一个进程至少有一个线程)
上述代码不够明显,没有多线程的感觉,进行修改一下:
此时交替的快速的输出 "hello Tread"和 "hello main",此时就是在"并发式"的执行
🙂 使用 jconsole 命令观察线程
可以通过Java提供的工具,更清楚的看到代码中的线程,jdk中包含的jconsole工具
目前还是一个可执行文件,我们双击运行他,通过这个进程可以去监视其他进程的运行状态
勾选本地连接,里面有一个
选择Demo1进行连接
会提示你不安全怎么怎么,直接选择不安全连接,进去之后选择进程窗口,就可以看到Java进程里面包含的所有线程情况
我们所运行的这个程序,一直在跑,在任务管理器中这个进程在疯狂的消耗cpu,主要是因为while true 循环太快了。
我们可以让while循环运行时,进行睡眠一下(单位是毫秒),不要速度太快,就是让线程主动进入"阻塞状态",主动放弃去cpu上执行,时间到了之后,线程才会解除阻塞状态(回到就绪态),重新被调度到cpu上执行。
此时sleep报错了,是因为可能会抛出一个受查异常,所有要通过try cath处理。
此时代码执行就变慢了,在观察任务管理器中的cpu占用率
加上 sleep就让cpu消耗的资源大幅度降低了
我们发现打印的结果是无序的,可能是main在前,Thread在前
📕 创建线程
共有5种写法,都很常用!!!
🚩方法一:继承 Thread 类
我们仔细观察代码发现,上述代码就是通过继承 Thread 类来创建线程的
观察发现,我们重写的是run方法,里面用于描述线程干了什么任务,为什么是通过 start 去调用呢
因为 start 调用的是操作系统提供的"创建线程"API,在内核中创建对于pcb,并且把pcb加入到链表中,进一步系统调度到这个进程之后,就会执行上述 run 方法中的逻辑。
他是Thread中自带的方法,通俗的来说run方法记录这个"事情",而strat就是要执行run里面的"事情"
如果不去调用start,直接调用run的话,就没有创建出新的线程,就是在主线程中执行myStart类里面的run进行循环打印,此时的run和主线程的循环就是串行执行,就没有"并发执行"这种效果,就必须要求run中的循环结束,才能继续执行到下一个循环!!!
像刚才谈到的run,只是定义好,而不去手动调用,把这个方法的调用,交给系统/其他的库/其他框架(别人)调用,这样的方法(函数)称为"回调函数"(callback function)
🚩 方法2:实现 Runnable 接口
在Runnable这个接口里面,只有一个方法(run)
Runnable的作用是描述一个"任务",这个任务和具体的执行机制无关(通过线程的方式执行,还是通过其他的方式执行),那么run也就是要执行的"任务"内容本身了
此时就和刚刚一并发的执行了
我们引入 Runnable 就是为了"解耦合",未来如果要更换成其他的方式来执行这些任务,那么改动的成本就比较低!!!
🚩方法3:其他变形
- 匿名内部类创建 Thread 子类对象
- 匿名内部类创建 Runnable 子类对象
- lambda 表达式创建 Runnable 子类对象
lambda表达式本质上就是针对匿名内部类的平替
注意:catch里面的异常处理可能不一样,和异常处理方式
在sleep异常处理的时候,在main方法发现有两种处理方式,第一种就是在main方法后面进行方法声明(throws),第二种就是进程try—>catch处理
在线程的run中就只有一个选择,只能进行try—>catch处理
原因:
上述的方法签名,重写......都是javac规定的。
相关文章:

【JavaEE初阶】线程的概念及创建
目录 📕 前言 📕 认识线程(Thread) 🚩 概念 😊线程是什么 🙂 为啥要有线程 😭 进程和线程的区别(面试题重点) 🤭 Java的线程和操作系统线程…...

0727,学什么学,周六就应该休息!!!!!
周六就应该休息,一天就忙了两小时也不是我的错喵 目录 UDP的小总结 01:使用select实现一个基于UDP的一对一即时聊天程序。 1.0 复读机服务器和树洞客户端 2.0 byby不了一点的敬业服务器!!! 今天到此为止&#x…...
【C#】获取DICOM图像像素的像素值
8位像素深度的像素值 public byte GetGreyValue(int x, int y) {x Math.Min(x, m_nWidth - 1);y Math.Min(y, m_nHeight - 1);unsafe{byte* greyValue (byte*)m_pDicomData.ToPointer() y * m_nWidth x;return *greyValue;} } 16位像素深度的像素值 public ushort GetG…...

k8s多集群管理工具kubecm
文章目录 一、概述二、安装1、官网链接2、各平台安装2.1、MacOS2.2、Linux2.3、Windows 三、实例1、验证2、配置kubecm自动补全(选做)2.1、Bash2.2、Zsh2.3、fish2.4、PowerShell 3、创建存放kubeconfig文件的目录4、添加到 $HOME/.kube/config4.1、kube…...

通过 WSL 2 在Windows 上挂载 Linux 磁盘
原文查看 曾为了传输或者共享不同系统的文件频繁地在 Windows 和 Linux 系统之间切换,效率过低,所以尝试通过 WSL 2 在Windows 上挂载 Linux 磁盘。 先决条件 需要在Windows 10 2004 及更高版本(Build 19041 及更高版本)或 Win…...
【C#】在一个给定的宽、高范围内,获取到该多边形内部的所有坐标集合?
问题点 使用C#语言在一个给定的宽、高范围内,获取到该多边形内部的所有坐标集合? 这个多边形可能存在交叉及互相重叠部分 图像的宽、高可以定义为:2000*2000 多边形坐标集合:Point[] polygon_points new Point[] { new Point…...
json的数据结构
JSON 的数据结构 JSON 由两种数据结构组成:对象(字典)和数组。 一、对象 对象(object)是由键值对组成的无序集合。 键是字符串,值可以是任何类型,包括对象和数组;对象由一对花括…...
html-docx-js和file-saver实现html导出word
依赖html-docx-js,file-saver,html2canvas import { asBlob } from html-docx-js/dist/html-docx; import { saveAs } from file-saver; import html2Canvas from html2canvas;const handleImageToBase64 (cloneEle) > {let imgElements cloneEle.…...

三维影像系统PACS源码,图像存储与传输系统,应用于医院中管理医疗设备如CT,MR等产生的医学图像的信息系统
PACS,即图像存储与传输系统,是应用于医院中管理医疗设备如CT,MR等产生的医学图像的信息系统。目标是支持在医院内部所有关于图像的活动,集成了医疗设备,图像存储和分发,数字图像在重要诊断和会诊时的显示&a…...

Golang | Leetcode Golang题解之第292题Nim游戏
题目: 题解: func canWinNim(n int) bool {return n%4 ! 0 }...
Redis在SpringBoot中配置
lettuce redis的使用方法有两种,jedis和lecttuce,jedis用的不是很多,下面讲解用lettuce的使用方法。 首先导包: <!--redis依赖--> <dependency><groupId>org.springframework.boot</groupId><artif…...

linux 网络子系统
__netif_receive_skb_core 是 Linux 内核网络子系统中一个非常重要的函数,它负责将网络设备驱动层接收到的数据包传递到上层协议栈进行处理。以下是对该函数的一些关键点的详细解析: 一、函数作用 __netif_receive_skb_core 函数是处理接收到的网络数据…...

JVM:垃圾回收器演进
文章目录 一、演进二、Shenandoah三、ZGC 一、演进 二、Shenandoah Shenandoah是由Red Hat开发的一款低延迟的垃圾收集器,Shenandoah并发执行大部分GC工作,包括并发的整理,堆大小对STW的时间基本没有影响。 三、ZGC ZGC是一种可扩展的低延…...

全新微软语音合成网页版源码,短视频影视解说配音网页版系统-仿真人语音
源码介绍 最新微软语音合成网页版源码,可以用来给影视解说和短视频配音。它是TTS文本转语言,API接口和PHP源码。 这个微软语音合成接口的源码,超级简单,就几个文件搞定。用的是官方的API,试过了,合成速度…...

大语言模型-对比学习-Contrastive Learning
一、对比学习概念 对比学习是一种特殊的无监督学习方法。 旨在通过拉近相关样本的距离并且推远不相关样本的距离,来学习数据表示。 通常使用一种高自由度、自定义的规则来生成正负样本。在模型预训练中有着广泛的应用。 二、对比学习小案例 对比学习主要分为三个…...
C++ 封装的用法
C(七)封装 封装,可以达到,对外提供接口,屏蔽数据,对内开放数据。 权限控制 struct 中所有行为和属性都是 public 的(默认),此举也是为了 C兼容 C 语言, 因为 C 语言中没有权限的概念。 C中的 class 可以…...

【C++11:异常】
目录 抛异常标准书写格式 抛异常如何执行? 指定抛出异常类型: noexcept 关键字:throw 抛异常标准书写格式 抛异常如何执行? 当212行的异常被抛出,程序会重新返回函数func中,在函数中去寻找catch 语句的…...

Dify中HTTP请求节点的常见操作
HTTP节点包括API请求类型(GET、POST、HEAD、PATCH、PUT、DELETE),鉴权类型(无、API-Key基础、API-Key Bearer、API-Key自定义),HEADERS键值设置,PARAMS键值设置,BODY(non…...

《大语言模型(赵鑫)》知识框图
...

【Android】性能实践—编码优化与布局优化学习笔记
编码优化 使用场景 如果需要拼接字符串,优先使用StringBuffer和StringBuilder进行凭借,他们的性能优于直接用加号进行拼接,因为使用加号连接符会创建多余的对象一般情况下使用基本数据类来代替封装数据类型(比如int优于Integer&…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...

Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...