JavaEE 【知识改变命运】02 多线程(1)
文章目录
- 线程是什么?
- 1.1概念
- 1.1.1 线程是什么?
- 1.1.2 为什么要有线程
- 1.1.3 进程和线程的区别
- 1.1.4 思考:执行一个任务,是不是创建的线程或者越多是不是越好?(比如吃包子比赛)
- 1.1.5 ) Java 的线程 和 操作系统线程 的关系
- 1.2 对多线程程序的理解
- 1.2.1 ) Java 的线程 和 操作系统线程 的关系
- 1.3 创建线程的两种方式
- 1.3.1 继承 Thread 类
- 1.3.2实现Runnable接口
- 1.3.3两者创建方法的对比
- 1.3.4 其他形式创建
- 1.3.4.1 匿名类创建Thread子类对象
- 1.3.4.2匿名内部类创建 Runnable ⼦类对象
- 1.3.4.2 lambda 表达式创建 Runnable ⼦类对象
- 1.4 jconsloe使用
线程是什么?
1.1概念
1.1.1 线程是什么?
- 线程是就是一个执行流,每个执行流之间都可以按照一定顺子执行自己的代码,多个线程可以”同时“执行多分代码
- 举例:进程就像一个程序,比如qq,迅雷,进程是程序的一次执行过程,或者是正在运行的一个程序,是动态的过程有它自己的产生存在和消亡的过程
- 线程是又进程创建的,是进程的一个实体,一个进程可以拥有多个线程,把迅雷比作一个进程,而同时下载多条视频,就是多条线程在工作。
1.1.2 为什么要有线程
- “并发式编成”已经成为了编成界的“刚需”
- 单核 CPU 的发展遇到了瓶颈. 要想提⾼算⼒, 就需要多核 CPU. ⽽并发编程能更充分利⽤多核 CPU资源.
- 有些任务场景需要 “等待 IO”, 为了让等待 IO 的时间能够去做⼀些其他的⼯作, 也需要⽤到并发编程.
- 重点:进程虽然可以进程并发编成,但是线程比进程更轻量。
解释:进程的创建也需要申请资源,而申请资源对于系统的性能影响比较大。
举个例子:张三要开一个工厂,工业园相当于是操作系统,地皮是固定的,张三的工厂就像一个进程,生产线就像一个线程,张三的工厂是生产皮包的,里面只有一条生产线,现在我们要提高产量,是重新建一个场比较好?,还是在原来的工厂中加一条生产线好呢?,肯定是只增加一条生产线,这样就节省了工业园地皮的面积资源,也利用张三工厂的面积资源,线程的出现更好的利用了系统的资源。
- 其次, 虽然多进程也能实现 并发编程, 但是线程⽐进程更轻量,
创建线程比创建进程更快
销毁线程比销毁进程更快
调度线程比调度进程更快。
- 线程虽然比进程更轻量,但是⼈们还不满⾜, 于是⼜有了 “线程池”(ThreadPool) 和 “协程”(Coroutine)
1.1.3 进程和线程的区别
1.进程里面包含线程:每一个进程里面至少包含一个主线程
2.进程是申请资源的最小单位
3.线程是cpu调度的最小单位
4.进程和进程之间不共享内存空间. 同⼀个进程的线程之间共享同⼀个内存空间 ,所以进程与进程之间互不影响,线程与线程之间可能产生影响
5.一个线程受到影响,会导致进程的结束,⼀个进程挂了⼀般不会影响到其他进程. 但6.是⼀个线程挂了, 可能把同进程内的其他线程⼀起带⾛(整个进程崩溃).
1.1.4 思考:执行一个任务,是不是创建的线程或者越多是不是越好?(比如吃包子比赛)
我们先思考下创造进程的方式:
虽然双进程比单进程确实提升了效率,但是消耗资源太大了,太浪费资源了
我们思考创建线程的方法
效率确实提高了,比进程消耗的资源小
我们再思考一下,根据上面的情况,我们无限创建线程,是不是线程创建的越多越好呢?
答案肯定不是的,这样会出现线程争抢资源问题,如果一个线程崩溃就会造成整个进程的崩溃
其实我们可以根据cpu的逻辑处理器来创建线程
当线程小于逻辑处理器,创建线程会提升效率
当线程大于逻辑处理器,创建线程的线程都是阻塞等待状态,从而没有发挥出线程的效果,创建线程本来就会消耗资源,从而白白消耗资源
- 总结:通过提升线程,我们可以提高效率,但是要根据实际情况来创建,不能盲目创建
1.1.5 ) Java 的线程 和 操作系统线程 的关系
线程是操作系统中的概念. 操作系统内核实现了线程这样的机制, 并且对⽤⼾层提供了⼀些 API 供⽤⼾使⽤(例如 Linux 的 pthread 库).Java 标准库中 Thread 类可以视为是对操作系统提供的 API 进⾏了进⼀步的抽象和封装.
1.2 对多线程程序的理解
1.2.1 ) Java 的线程 和 操作系统线程 的关系
- 线程是操作系统中的概念. 操作系统内核实现了线程这样的机制, 并且对⽤⼾层提供了⼀些 API 供⽤⼾使⽤(例如 Linux 的 pthread 库).Java 标准库中 Thread 类可以视为是对操作系统提供的 API 进⾏了进⼀步的抽象和封装.
- 线程与普通程序的区别:每个线程都是⼀个独⽴的执⾏流,多个线程之间是 “并发” 执⾏的
import java.util.Random; public class ThreadDemo {private static class MyThread extends Thread {@Overridepublic void run() {Random random = new Random();while (true) {// 打印线程名称System.out.println(Thread.currentThread().getName());try {// 随机停⽌运⾏ 0-9 秒Thread.sleep(random.nextInt(10));} catch (InterruptedException e) {e.printStackTrace();}}}}public static void main(String[] args) {MyThread t1 = new MyThread();t1.start();Random random = new Random();while (true) {// 打印线程名称System.out.println(Thread.currentThread().getName());try {Thread.sleep(random.nextInt(10));} catch (InterruptedException e) {// 随机停⽌运⾏ 0-9 秒e.printStackTrace();}}} }
我们可以jconsole这个工具查看线程
里面有一个mian主线程,和Thread-0子线程
1.3 创建线程的两种方式
1.3.1 继承 Thread 类
@Override//自定义的线程的执行体,线程执行的代码写在这里public void run(){while (true){System.out.println("hello myThread ");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}} } class Main{public static void main(String[] args) {MyThread myThread=new MyThread();//创建一个线程对象myThread.start();//启动线程while (true){System.out.println("hello mainThread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
1:PCB是操作系统层面的
2:Thread是java层面的线程。两者是一 一对应的
3:过程:java创建一个线程------jvm调用系统API--------创建系统中线程------参与调度cpu
4. 线程执行的顺序是没有规律的,跟cpu的调度有关,因为cpu是“抢占式”执行,所以那个线程当前占用cpu资源是不能确定的
5.能不能调用run()方法执行线程,答案是不行的,因为run方法是java层面的,是不能启动线程的。
6:
start()开始后,并不意味着线程立马执行,
1.3.2实现Runnable接口
@Overridepublic void run() {while (true){System.out.println("hello myRunnable");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}} class Main{public static void main(String[] args) {MyRunnable myRunnable=new MyRunnable();//创建一个线程任务对象// 创建 Thread 类实例, 调⽤ Thread 的构造⽅法时将 Runnable 对象作为 target 参数.Thread thread=new Thread(myRunnable);//创建一个线程对象,thread.start();//启动线程while (true){System.out.println("hello mainThread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}} } ```
这种方法实现底层原码过程:
其实这种模式是一种及简化的代理模式,这里模拟实现一下
//模拟实现一个Thread类的代理类,模拟Thread的启动
public class ThreadProxy implements Runnable{private Runnable target;public ThreadProxy(Runnable target) {this.target = target;}@Overridepublic void run(){if (target!=null){target.run();}}public void start(){start0();}private void start0() {run();}}
class Main{public static void main(String[] args) {
// ThreadProxy threadProxy01 = new ThreadProxy(new Runnable() {
// @Override
// public void run() {
// while (true){
// System.out.println("hello myRunnable");
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
// }
// });
// threadProxy01.start();Tiger tiger = new Tiger();ThreadProxy threadProxy02 = new ThreadProxy(tiger);threadProxy02.start();}
}
class animal {
}
class Tiger extends animal implements Runnable{public void run(){System.out.println("老虎嗷嗷叫");}
}
1.3.3两者创建方法的对比
- 继承 Thread 类, 直接使⽤ this 就表⽰当前线程对象的引⽤.
- 实现 Runnable 接⼝, this 表⽰的是 MyRunnable 的引⽤. 需要使⽤Thread.currentThread()
- java是单继承模式,在某种情况下一个类可能已经继承某个父类,这时在用来继承Thread类的方法创造线程是显然不可能的
- 实现 Runnable 接⼝,实现了高内聚低耦合的特点,线程和业务逻辑分开,后面修改代码时候,相互影响最小化。
解释:举例一个场景:两条生成皮鞋的生产线,一条生产皮包生产线
1.3.4 其他形式创建
1.3.4.1 匿名类创建Thread子类对象
public class Main {public static void main(String[] args) {Thread t1=new Thread(){@Overridepublic void run() {while (true){System.out.println("hello myThread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}};t1.start();}}
1.3.4.2匿名内部类创建 Runnable ⼦类对象
public class Main {public static void main(String[] args) {Thread t2=new Thread(new Runnable(){@Overridepublic void run() {while (true){System.out.println("hello myRunnable");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}});t2.start();}
}
1.3.4.2 lambda 表达式创建 Runnable ⼦类对象
public class Main {public static void main(String[] args) {Thread t3=new Thread(()->{while (true){System.out.println("hello myLambda");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t3.start();}}
1.4 jconsloe使用

我们这里重提一下,先调用的方法会先入栈,后调用的后入栈,后调用的方法执行完后就会出栈。
相关文章:
JavaEE 【知识改变命运】02 多线程(1)
文章目录 线程是什么?1.1概念1.1.1 线程是什么?1.1.2 为什么要有线程1.1.3 进程和线程的区别1.1.4 思考:执行一个任务,是不是创建的线程或者越多是不是越好?(比如吃包子比赛)1.1.5 ) Java 的线程…...
Pytorch使用手册-Transforms(专题四)
Transforms(变换) 在 PyTorch 数据处理中的重要性和使用方法,特别是如何通过 torchvision.transforms 模块对数据进行预处理和变换,使其适合用于训练机器学习模型。以下是具体的内容解读: 什么是 Transforms? 数据通常在收集后并非直接适合用于训练机器学习模型,需要通…...
【Android】ARouter的使用及源码解析
文章目录 简介介绍作用 原理关系 使用添加依赖和配置初始化SDK添加注解在目标界面跳转界面不带参跳转界面含参处理返回结果 源码基本流程getInstance()build()navigation()_navigation()Warehouse ARouter初始化init帮助类根帮助类组帮助类 completion 总结 简介 介绍 ARouter…...
ValueError: bbox_params must be specified for bbox transformations
错误 ValueError: bbox_params must be specified for bbox transformations 是因为使用了需要处理边界框(bboxes)的增强操作,但在 albumentations.Compose 中没有正确设置bbox_params 参数。 bbox_params 是用来指定如何处理边界框的配置。…...
挂壁式空气净化器哪个品牌的质量好?排名top3优秀产品测评分析
随着挂壁式空气净化器市场的不断扩大,各类品牌与型号琳琅满目。但遗憾的是,一些跨界网红品牌过于追求短期效益,导致产品在净化效果与去除异味方面表现平平,使用体验不佳,甚至可能带来二次污染风险,影响人体…...
钉钉数据如何高效集成到金蝶云星空系统
钉钉数据集成到金蝶云星空的技术案例分享 在企业日常运营中,办公用品采购流程的高效管理至关重要。为了实现这一目标,我们采用了轻易云数据集成平台,将钉钉中的采购申请单数据无缝对接到金蝶云星空系统中。本次案例将详细解析【办公用品采购…...
躺平成长-腾讯云数据库(又消失了一次)
开源竞争: 当你无法彻底掌握技术的时候,你就开源这个技术,形成更多的技术依赖,你会说 这不就是在砸罐子吗?一个行业里面总会有人砸罐子的,你不如先砸罐子,还能听个响声。 数据库的里面清洁的数据…...
初学 flutter 问题记录
windows搭建flutter运行环境 一、运行 flutter doctor遇到的问题 Xcmdline-tools component is missingRun path/to/sdkmanager --install "cmdline-tools;latest"See https://developer.android.com/studio/command-line for more details.1)cmdline-to…...
Hadoop的MapReduce详解
文章目录 Hadoop的MapReduce详解一、引言二、MapReduce的核心概念1、Map阶段1.1、Map函数的实现 2、Reduce阶段2.1、Reduce函数的实现 三、MapReduce的执行流程四、MapReduce的使用实例Word Count示例1. Mapper类2. Reducer类3. 执行Word Count 五、总结 Hadoop的MapReduce详解…...
全新配置ubuntu18.04深度学习环境
1、下载显卡驱动 1.1、驱动下载 连接:显卡驱动 手动驱动搜索-》查找-》查看-》下载 下载可使用指令 wget https://us.download.nvidia.com/XFree86/Linux-x86_64/535.216.01/NVIDIA-Linux-x86_64-535.216.01.run 2、下载安装cuda12.0 wget https://developer.do…...
持续集成与持续部署:CI/CD实现教程
以下是一个基于常见工具实现 CI/CD 的基本教程示例,这里以 Git、Jenkins、Maven(用于 Java 项目构建和管理依赖,其他语言项目可替换为对应构建工具)以及 Docker(用于容器化部署,非必需但很常用)…...
深度学习实验十二 卷积神经网络(3)——基于残差网络实现手写体数字识别实验
目录 一、模型构建 1.1残差单元 1.2 残差网络的整体结构 二、统计模型的参数量和计算量 三、数据预处理 四、没有残差连接的ResNet18 五、带残差连接的ResNet18 附:完整的可运行代码 实验大体步骤: 先前说明: 上次LeNet实验用到的那…...
Linux系统如何排查端口占用
如何在Linux系统中排查端口占用 在Linux系统中,当您遇到网络服务无法启动或响应异常的情况时,可能是因为某个特定的端口已经被其他进程占用。这时,您需要进行端口占用情况的排查来解决问题。本文将介绍几种常用的命令行工具和方法࿰…...
Linux常用命令之id命令详解
id命令详解 id 命令在 Linux 和 Unix 系统中用于显示用户的标识信息,包括用户ID(UID)、组ID(GID)以及用户所属的附加组。这个命令对于系统管理员和开发者来说非常有用,因为它能帮助他们确认运行命令或脚本…...
WGCLOUD如何部署在ARM平台
WGCLOUD是一款开源免费的运维平台,非常强大方便,可以帮我们提高运维效率 我们项目中,大部分是ARM的服务器,那么如何部署WGCLOUD呢,其实挺简单的 首先是部署服务端server 我们只要安装好对应ARM版本的JDK,…...
K8S + Jenkins 做CICD
前言 这里会做整体CICD的思路和流程的介绍,会给出核心的Jenkins pipeline脚本,最后会演示一下 实验/实操 结果 由于整体内容较多,所以不打算在这里做每一步的详细演示 - 本文仅作自己的实操记录和日后回顾用 要看保姆式教学的可以划走了&…...
HarmonyOS4+NEXT星河版入门与项目实战(11)------Button组件
文章目录 1、控件图解2、案例实现1、代码实现2、代码解释3、运行效果4、总结1、控件图解 这里我们用一张完整的图来汇整 Button 的用法格式、属性和事件,如下所示: 按钮默认类型就是胶囊类型。 2、案例实现 这里我们实现一个根据放大和缩小按钮来改变图片大小的功能。 功…...
小米note pro一代(leo)线刷、twrp、magisk、TODO: android源码编译
本文主要说android5 整体思路 android 5.1 twrp magisk Zygisk(Riru) Dreamland(xposed) Riru不支持android5.1, 因此只能选择Zygisk : 如果你正在使用 Android 5,你必须使用 Zygisk 因为 Riru 并不支持 Android 5. 基于magisk之上的xposed 其中提到的 作者…...
鸿蒙开发Hvigor插件动态生成代码
Hvigor允许开发者实现自己的插件,开发者可以定义自己的构建逻辑,并与他人共享。Hvigor主要提供了两种方式来实现插件:基于hvigorfile脚本开发插件、基于typescript项目开发。下面以基于hvigorfile脚本开发插件进行介绍。 基于hvigorfile脚本…...
使用ENSP实现静态路由
一、双路由器静态路由 1.项目拓扑 2.项目实现 (1)路由器AR1配置 进入系统试图 sys将路由器命名为R1 sysname R1进入g0/0/0接口 int g0/0/0将g0/0/0接口IP地址配置为1.1.1.1/24 ip address 1.1.1.1 24进入g0/0/1接口 int g0/0/1将g0/0/1接口IP地址配置为192.168.1.1/24 ip ad…...
从零开始理解反步控制:用李雅普诺夫函数一步步‘后退’设计控制器(附Simulink仿真模型)
非线性控制实战:用反步法构建稳定系统的可视化指南 在控制理论中,非线性系统总是以其复杂的动态特性让工程师们又爱又恨。传统的线性控制方法往往难以应对这种复杂性,而反步控制(Backstepping Control)作为一种系统化的…...
图深度学习文献宝库LiteratureDL4Graph:一站式掌握图神经网络研究进展
图深度学习文献宝库LiteratureDL4Graph:一站式掌握图神经网络研究进展 【免费下载链接】LiteratureDL4Graph 项目地址: https://gitcode.com/gh_mirrors/li/LiteratureDL4Graph 想要快速掌握图神经网络(GNN)和图深度学习的最新研究进展吗?Litera…...
CogVideoX-2b完整功能测评:一键部署+本地渲染+隐私安全全解析
CogVideoX-2b完整功能测评:一键部署本地渲染隐私安全全解析 1. 为什么选择本地化视频生成工具 在内容创作领域,视频制作一直是门槛较高的技能。传统视频制作需要专业的剪辑软件、大量的素材积累以及复杂的时间线操作。而云端视频生成服务虽然降低了技术…...
影刀RPA实战:用Python字符串处理提升自动化效率(附5个常用脚本)
影刀RPA实战:5个Python字符串处理脚本解决自动化难题 在影刀RPA的自动化流程中,字符串处理就像流水线上的精密工具,直接决定了数据处理的准确性和效率。当我们需要从混乱的日志中提取关键信息、清洗客户提交的表格数据或转换不同系统的文本格…...
别再只用L1/L2了!用PyTorch实战图像修复的5种高阶损失函数(含VGG19感知损失代码)
超越L1/L2:PyTorch图像修复中5种高阶损失函数的工程实践 当你在深夜调试一个图像超分辨率模型时,发现生成的图片虽然PSNR值很高,但总感觉缺少那种"真实感"——边缘不够锐利,纹理略显模糊。这时候,L1/L2损失函…...
vue基于springboot架构的酒店管理系统 酒店商城购物系统
目录同行可拿货,招校园代理 ,本人源头供货商功能模块分析技术实现要点扩展功能建议项目技术支持源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作同行可拿货,招校园代理 ,本人源头供货商 功能模块分析 酒店管理系统功能 客房管理ÿ…...
原创:行业空白:从约束崩塌到系统闭环的工程新论
行业空白:从约束崩塌到系统闭环的工程新论 作者:华夏之光永存 #工程约束 #底层架构 #系统稳定性 #软件开发 #高端制造 #工程方法论 #逻辑闭环 #零缺陷工程 #源头治理 #技术架构 摘要 本文直指当前工程领域普遍存在的核心问题:缺乏统一、刚性的…...
内存取证新手必看:用Lovelymem+MemProcFS挂载分析,像访问文件夹一样查看RAW镜像
内存取证革命:用LovelymemMemProcFS实现零命令行分析 想象一下,当你拿到一个18GB的内存镜像文件时,不再需要面对密密麻麻的命令行参数和漫长的等待时间。传统内存取证工具如Volatility虽然强大,但对于初学者来说,记忆各…...
Graphormer部署教程:/etc/supervisor/conf.d/graphormer.conf配置解析
Graphormer部署教程:/etc/supervisor/conf.d/graphormer.conf配置解析 1. 项目介绍 Graphormer是一种基于纯Transformer架构的图神经网络模型,专门为分子图(原子-键结构)的全局结构建模与属性预测而设计。该模型在OGB、PCQM4M等…...
KEPServerEX与SQLServer数据库的无缝集成指南
1. KEPServerEX与SQLServer集成的核心价值 在工业自动化和数据采集领域,KEPServerEX作为领先的通信平台,与SQLServer数据库的集成能够实现设备数据到关系型数据库的高效流转。这种组合特别适合需要长期存储设备运行数据、生成生产报表或进行数据分析的场…...















