多线程-初阶(1)
1. 认识线程(Thread)
1.1 概念
1) 线程是什么
线程之间的共享变量存在 主内存 (Main Memory).每⼀个线程都有⾃⼰的 "⼯作内存" (Working Memory) .当线程要读取⼀个共享变量的时候, 会先把变量从主内存拷⻉到⼯作内存, 再从⼯作内存读取数据.
- 进程是包含线程的. 每个进程⾄少有⼀个线程存在,即主线程。
- 进程和进程之间不共享内存空间. 同⼀个进程的线程之间共享同⼀个内存空间。
- 进程是系统分配资源的最⼩单位,线程是系统调度的最⼩单位。
- ⼀个进程挂了⼀般不会影响到其他进程. 但是⼀个线程挂了, 可能把同进程内的其他线程⼀起带⾛(整个进程崩溃).
4) Java 的线程 和 操作系统线程 的关系
1.2 第⼀个多线程程序
• 每个线程都是⼀个独⽴的执⾏流• 多个线程之间是 "并发" 执⾏的.
可以使用jconsole观察线程的状态,具体怎么使用后面学习.
1.3 创建线程

class MyThread extends Thread {@Overridepublic void run() {System.out.println("这⾥是线程运⾏的代码");}
} MyThread t = new MyThread(); t.start(); // 线程开始运⾏ class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("这⾥是线程运⾏的代码");}
} Thread t = new Thread ( new MyRunnable ());
方法3:匿名内部类,创建Thread子类

方法4:匿名内部类,创建Runnable子类
方法5:lambda表达式

2. Thread 类及常⻅⽅法
2.1 Thread 的常⻅构造⽅法

演示:
Thread t1 = new Thread();
Thread t2 = new Thread(new MyRunnable());
Thread t3 = new Thread("这是我的名字");
Thread t4 = new Thread(new MyRunnable(), "这是我的名字");
2.1 Thread 的⼏个常⻅属性(重点)
| 属性 | 获取方法 |
| ID | getId() |
| 名称 | getName() |
| 状态 | getState() |
| 优先级 | getPriority() |
| 是否为后台线程 | isDaemon() |
| 是否存活 | isAlive() |
| 是否被中断 | isInterrupted() |
解释:
ID 是线程的唯⼀标识,不同线程不会重复名称是各种调试⼯具⽤到状态表⽰线程当前所处的⼀个情况,下⾯我们会进⼀步说明优先级⾼的线程理论上来说更容易被调度到(抢占资源)关于后台线程,需要记住⼀点: JVM会在⼀个进程的所有⾮后台线程结束后,才会结束运⾏。是否存活,即简单的理解,为 run ⽅法是否运⾏结束了线程的中断问题,等等我们会解释到。
是否为后台线程:

一次都没有打印就结束,因为main线程结束的很快。mian是前台线程,thread是后台线程。也可以判断线程是否为后台线程。

是否存活:

2.2线程的中断(重点)
⽬前常⻅的有以下两种⽅式:
1. 通过共享的标记来进⾏沟通2. 调⽤ interrupt() ⽅法来通知
标志位 中断(终止)
调用intterrupt()

解释

但是这里有一个问题:
会一直陷入死循环,为什么,
解释:

解决方法:
加上break

2.3等待⼀个线程 - join()
比如说:现在有两线程a,b,在a线程中调用b.join()
就是a线程等待b线程先结束,a线程在执行。


join的作用:就是能让先结束的线程先结束

2.4 获取当前线程引⽤
这个方法我们已经很熟悉了,用来获取当前线程的引用。

2.5休眠当前线程(sleep)

3. 线程的状态
打印线程状态:线程变量名.getState();

这个我就不多演示,后面我会给大家带来jcomsole工具,java自带工具的使用。
4. 多线程带来的的⻛险-线程安全 (重点)
4.1 观察线程不安全
比如说:现在让两个
代码:
public class Demo9 {private static int count = 0;public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {// 对 count 变量增5w次for (int i = 0; i < 50000; i++) {count++;}});Thread t2 = new Thread(() -> {// 对 count 变量增5w次for (int i = 0; i < 50000; i++) {count++;}});t1.start();t2.start();t1.join();t2.join();// 预期结果应该是 10wSystem.out.println("count: " + count);}
}
结果:

原因:

4.2 线程安全的概念
4.3 线程不安全的原因
什么是原⼦性
可⻅性

- 线程之间的共享变量存在 主内存 (Main Memory).
- 每⼀个线程都有⾃⼰的 "⼯作内存" (Working Memory) .
- 当线程要读取⼀个共享变量的时候, 会先把变量从主内存拷⻉到⼯作内存, 再从⼯作内存读取数据.
- 当线程要修改⼀个共享变量的时候, 也会先修改⼯作内存中的副本, 再同步回主内存.
由于每个线程有⾃⼰的⼯作内存, 这些⼯作内存中的内容相当于同⼀个共享变量的 "副本". 此时修改线程1 的⼯作内存中的值, 线程2 的⼯作内存不⼀定会及时变化.
演示过程:
1) 初始情况下, 两个线程的⼯作内存内容⼀致.

2) 为啥要这么⿇烦的拷来拷去?
⽐如某个代码中要连续 10 次读取某个变量的值, 如果 10 次都从内存读, 速度是很慢的. 但是如果只是 第⼀次从内存读, 读到的结果缓存到 CPU 的某个寄存器中, 那么后 9 次读数据就不必直接访问内存了. 效率就⼤⼤提⾼了.
4.4 解决之前的线程不安全问题
代码:
public class Demo9 {private static int count = 0;public static void main(String[] args) throws InterruptedException {Object locker = new Object();Thread t1 = new Thread(() -> {// 对 count 变量进⾏⾃增 5w 次for (int i = 0; i < 50000; i++) {synchronized (locker) {count++;}}});Thread t2 = new Thread(() -> {// 对 count 变量进⾏⾃增 5w 次for (int i = 0; i < 50000; i++) {synchronized (locker) {count++;}}});t1.start();t2.start();t1.join();t2.join();// 预期结果应该是 10wSystem.out.println("count: " + count);}
}
结果:

5. synchronized 关键字 - 监视器锁 monitor lock
5.1 synchronized 的特性
1) 互斥
进⼊ synchronized 修饰的代码块, 相当于 加锁退出 synchronized 修饰的代码块, 相当于 解锁

synchronized⽤的锁是存在Java对象头⾥的。


上⼀个线程解锁之后, 下⼀个线程并不是⽴即就能获取到锁. ⽽是要靠操作系统来 "唤醒". 这也就 是操作系统线程调度的⼀部分⼯作.•假设有 A B C 三个线程, 线程 A 先获取到锁, 然后 B 尝试获取锁, 然后 C 再尝试获取锁, 此时 B 和 C 都在阻塞队列中排队等待. 但是当 A 释放锁之后, 虽然 B ⽐ C 先来的, 但是 B 不⼀定就能获取到锁, ⽽是和 C 重新竞争, 并不遵守先来后到的规则.
2) 可重⼊
理解 "把⾃⼰锁死"
⼀个线程没有释放锁, 然后⼜尝试再次加锁.// 第⼀次加锁, 加锁成功lock();// 第⼆次加锁, 锁已经被占⽤, 阻塞等待.lock();按照之前对于锁的设定, 第⼆次加锁的时候, 就会阻塞等待. 直到第⼀次的锁被释放, 才能获取到第⼆个锁. 但是释放第⼀个锁也是由该线程来完成, 结果这个线程已经躺平了, 啥都不想⼲了, 也就⽆法进 ⾏解锁操作. 这时候就会 死锁。
这样的锁称为 不可重⼊锁.
Java 中的 synchronized 是 可重⼊锁,像c++和python是不可重入锁。
5.2 synchronized 使⽤⽰例
1) 修饰代码块: 明确指定锁哪个对象.
public class SynchronizedDemo {private Object locker = new Object();public void method() {synchronized (locker) {}}
} public class SynchronizedDemo {public void method() {synchronized (this) {}}
} 2) 直接修饰普通⽅法: 锁的 SynchronizedDemo 对象
public class SynchronizedDemo {public synchronized void methond() {}
} 3) 修饰静态⽅法: 锁的 SynchronizedDemo 类的对象
public class SynchronizedDemo {public synchronized static void method() {}
} 
5.3 Java 标准库中的线程安全类
但是还有⼀些是线程安全的. 使⽤了⼀些锁机制来控制。
还有的虽然没有加锁, 但是不涉及 "修改", 仍然是线程安全的
String
6. volatile 关键字
来我们写一个代码,只要输入0就会停止线程。
代码:
public class Demo10 {static volatile int n = 0;public static void main(String[] args) {Thread t1 = new Thread(() -> {while(true) {//啥都不写}});Thread t2 = new Thread(() -> {Scanner sc = new Scanner(System.in);System.out.println("请输入一个整数:");n = sc.nextInt();});}
}
结果:

结果捏

这就是可见性问题。
原因:


volatile 不保证原⼦性
public class Demo9 {private volatile static int count = 0;public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {for (int i = 0; i < 50000; i++) {count++;}});Thread t2 = new Thread(() -> {// 对 count 变量进⾏⾃增 5w 次for (int i = 0; i < 50000; i++) {count++;}});t1.start();t2.start();t1.join();t2.join();// 预期结果应该是 10wSystem.out.println("count: " + count);}
}
好了今天就讲到这里。
相关文章:
多线程-初阶(1)
本节⽬标 • 认识多线程 • 掌握多线程程序的编写 • 掌握多线程的状态 • 掌握什么是线程不安全及解决思路 • 掌握 synchronized、volatile 关键字 1. 认识线程(Thread) 1.1 概念 1) 线程是什么 ⼀个线程就是⼀个 "执⾏流". 每个线…...
Spring Boot集成encache快速入门Demo
1.什么是encache EhCache 是一个纯 Java 的进程内缓存框架,具有快速、精干等特点,是 Hibernate 中默认的 CacheProvider。 Ehcache 特性 优点 快速、简单支持多种缓存策略:LRU、LFU、FIFO 淘汰算法缓存数据有两级:内存和磁盘&a…...
【C语言】数组练习
【C语言】数组练习 练习1:多个字符从两端移动,向中间汇聚练习2、二分查找 练习1:多个字符从两端移动,向中间汇聚 编写代码,演示多个字符从两端移动,向中间汇聚 练习2、二分查找 在⼀个升序的数组中查找指…...
微服务实战——ElasticSearch(保存)
商品上架——ElasticSearch(保存) 0.商城架构图 1.商品Mapping 分析:商品上架在 es 中是存 sku 还是 spu ? 检索的时候输入名字,是需要按照 sku 的 title 进行全文检索的检索使用商品规格,规格是 spu 的…...
leetcode练习 路径总和II
给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。 叶子节点 是指没有子节点的节点。 示例 1: 输入:root [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum 22 输出&a…...
使用Three.js库创建的简单WebGL应用程序,主要用于展示具有不同透明度和缩放比例的圆环列
上述HTML文档是一个使用Three.js库创建的简单WebGL应用程序,主要用于展示具有不同透明度和缩放比例的圆环列。以下是代码的详细解释: HTML结构: 文档类型声明为HTML5。<html>标签设置了语言属性为英语(lang"en")…...
Redis: 集群架构,优缺点和数据分区方式和算法
集群 集群指的就是一组计算机作为一个整体向用户提供一组网络资源 我就举一个简单的例子,比如百度,在北京和你在上海访问的百度是同一个服务器吗?答案肯定是不是的,每一个应用可以部署在不同的地方,但是我们提供的服务…...
负载均衡可以在网络模型的哪一层?
一、网络模型概述 网络模型是用于描述网络通信过程和网络服务的抽象框架。最常见的网络模型有两种:OSI(开放式系统互联)模型和TCP/IP模型。 OSI模型 OSI(Open Systems Interconnection)模型是由国际标准化组织&…...
YOLOv11改进 | 上采样篇 | YOLOv11引入CARAFE上采样
1. DySample介绍 1.1 摘要:特征上采样是许多现代卷积网络体系结构(如特征金字塔)中的关键操作。它的设计对于密集预测任务(如对象检测和语义/实例分割)至关重要。在本文中,我们提出了一个通用、轻量级、高效的特征重组算子CARAFE来实现这一目标.CARAFE有几个吸引人的特性…...
【Linux运维】grep命令粗浅学习
文章目录 1 背景介绍1.1 为什么要学习grep?1.2 grep是什么?1.3 grep可以做什么? 2 grep基本语法2.1 命令格式2.2 “PATTERN”部分中的正则表达式语法学习2.3 grep命令参数学习 3 典型案例3.1 匹配非空行,过滤纯空行3.2 匹配IPv4地…...
【Godot4.3】匀速和匀变速直线运动粒子
概述 本篇论述,如何用加速度在Godot中控制粒子运动。 匀速和匀变速直线运动的统一 以下是匀变速运动的速度和位移公式: v t v 0 a t x t v 0 t 1 2 a t 2 v_tv_0 at \\ x_tv_0t \frac{1}{2}at^2 vtv0atxtv0t21at2 当a 0 时…...
基于Hive和Hadoop的用电量分析系统
本项目是一个基于大数据技术的用电量分析系统,旨在为用户提供全面的电力消耗信息和深入的用电量分析。系统采用 Hadoop 平台进行大规模数据存储和处理,利用 MapReduce 进行数据分析和处理,通过 Sqoop 实现数据的导入导出,以 Spark…...
一个简单的摄像头应用程序4
我们进一步完善了这个app01.py,我们优化了界面使其更人性化,下面介绍中包含了原有的功能及新增的功能: 创建和管理文件夹: create_folder 函数用于创建保存照片和视频的文件夹。 get_next_file_number 函数用于获取文件夹中下一个可用的文件编号。 图像处理: pil_to_cv 函…...
SpringBoot使用EasyPoi根据模板导出word or pdf
1、导出效果 1.1 wrod 1.2 pdf 2、依赖 <!--word--><dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-base</artifactId><version>4.3.0</version></dependency><dependency><groupId>cn.…...
NVIDIA Hopper 架构深入
在 2022 年 NVIDIA GTC 主题演讲中,NVIDIA 首席执行官黄仁勋介绍了基于全新 NVIDIA Hopper GPU 架构的全新 NVIDIA H100 Tensor Core GPU。 文章目录 前言一、NVIDIA H100 Tensor Core GPU 简介二、NVIDIA H100 GPU 主要功能概述1. 新的流式多处理器 (SM) 具有许多性能和效率…...
AWS IoT Core for Amazon Sidewalk
目录 1 前言2 AWS IoT2.1 准备条件2.2 创建Credentials2.2.1 创建user2.2.2 配置User 2.3 本地CLI配置Credentials 3 小结 1 前言 在测试Sidewalk时,device发送数据,网关接收到,网关通过网络发送给NS,而此处用到的NS是AWS IoT&am…...
今日指数项目项目集成RabbitMQ与CaffienCatch
今日指数项目项目集成RabbitMQ与CaffienCatch 一. 为什么要集成RabbitMQ 首先CaffeineCatch 是作为一个本地缓存工具 使用CaffeineCatch 能够大大较少I/O开销 股票项目 主要分为两大工程 --> job工程(负责数据采集) , backend(负责业务处理) 由于股票的实时性也就是说 ,…...
C0005.Clion中移动ui文件到新目录后,报错问题的解决
报错问题如下 AutoUic error ------------- "SRC:/confirmwizardpage.cpp" includes the uic file "ui_confirmwizardpage.h", but the user interface file "confirmwizardpage.ui" could not be found in the following directories"SRC…...
基于STM32的智能家居灯光控制系统设计
引言 本项目将使用STM32微控制器实现一个智能家居灯光控制系统,能够通过按键、遥控器或无线模块远程控制家庭照明。该项目展示了如何结合STM32的外设功能,实现对灯光的智能化控制,提升家居生活的便利性和节能效果。 环境准备 1. 硬件设备 …...
06.useEffect
在 React 开发中,正确使用 useEffect 钩子对于优化组件性能至关重要。一个常见但容易被忽视的性能问题是在依赖数组中使用对象作为依赖项。这可能导致不必要的效果重新执行,从而影响应用性能。通过优先使用原始值(如字符串、数字)作为依赖项,我们可以显著提高组件的效率。…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
