Java之线程篇四

目录
volatile关键字
volatile保证内存可见性
代码示例
代码示例2-(+volatile)
volatile不保证原子性
synchronized保证内存可见性
wait()和notify()
wait()方法
notify()
理解notify()和notifyAll()
wait和sleep的对比
volatile关键字
volatile保证内存可见性
volatile 修饰的变量, 能够保证 "内存可见性".

代码在写入 volatile 修饰的变量的时候:
改变线程工作内存中volatile变量副本的值
将改变后的副本的值从工作内存刷新到主内存
代码在读取 volatile 修饰的变量的时候:
从主内存中读取volatile变量的最新值到线程的工作内存中
从工作内存中读取volatile变量的副本
加上 volatile , 强制读写内存. 速度是慢了, 但是数据变的更准确了。
代码示例
public class Demo13 {private static int isQuit=0;public static void main(String[] args) {Thread t1=new Thread(()->{while(isQuit==0){}System.out.println("t1 退出");});t1.start();Thread t2=new Thread(()->{System.out.println("请输入 isQuit:");Scanner scanner=new Scanner(System.in);isQuit=scanner.nextInt();});t2.start();}
}
运行结果

通过jconsole观察,会看到线程t1处于RUNNABLE状态。

t1 读的是自己工作内存中的内容 .当 t2 对 flag 变量进行修改 , 此时 t1 感知不到 flag 的变化 .
原因解释:
1) load 读取内存中isQuit的值到寄存器中.
2)通过cmp 指令比较寄存器的值是否是0.决定是否要继续循环.
由于这个循环,循环速度飞快.短时间内,就会进行大量的循环.也就是进行大量的load和cmp 操作.此时,编译器/JVM就发现了,虽然进行了这么多次load,但是 load 出来的结果都一样的.并且, load 操作又非常费时间,一次load花的时间相当于上万次cmp 了.
所以编译器就做了一个大胆的决定~~只是第一次循环的时候才读了内存.后续都不再读内存了,而是直接从寄存器中,取出isQuit的值了.
代码示例2-(+volatile)
public class Demo13 {private static volatile int isQuit=0;public static void main(String[] args) {Thread t1=new Thread(()->{while(isQuit==0){}System.out.println("t1 退出");});t1.start();Thread t2=new Thread(()->{System.out.println("请输入 isQuit:");Scanner scanner=new Scanner(System.in);isQuit=scanner.nextInt();});t2.start();}
}
运行结果

代码示例3-(+sleep)
public class Demo13 {private static int isQuit=0;public static void main(String[] args) {Thread t1=new Thread(()->{while(isQuit==0){try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}System.out.println("t1 退出");});t1.start();Thread t2=new Thread(()->{System.out.println("请输入 isQuit:");Scanner scanner=new Scanner(System.in);isQuit=scanner.nextInt();});t2.start();}
}
运行结果

volatile不保证原子性
代码示例
class Counter {volatile public int count = 0;void increase() {count++;}
}public class Demo13 {public static void main(String[] args) throws InterruptedException {final Counter counter = new Counter();Thread t1 = new Thread(() -> {for (int i = 0; i < 50000; i++) {counter.increase();}});Thread t2 = new Thread(() -> {for (int i = 0; i < 50000; i++) {counter.increase();}});t1.start();t2.start();t1.join();t2.join();System.out.println(counter.count);}
}
运行结果

我们会发现,加上volatile以后,依旧不是线程安全的。
synchronized保证内存可见性
代码示例
class Counter {public int flag = 0;
}public class Demo13 {public static void main(String[] args) {Counter counter = new Counter();Thread t1 = new Thread(() -> {while (true) {synchronized (counter) {if (counter.flag != 0) {break;}}}System.out.println("循环结束!");});Thread t2 = new Thread(() -> {Scanner scanner = new Scanner(System.in);System.out.println("输入一个整数:");counter.flag = scanner.nextInt();});t1.start();t2.start();}
}
运行结果

wait()和notify()
wait()方法
wait 做的事情:
使当前执行代码的线程进行等待. (把线程放到等待队列中)
释放当前的锁
满足一定条件时被唤醒, 重新尝试获取这个锁.
wait 要搭配 synchronized 来使用. 脱离 synchronized 使用 wait 会直接抛出异常.
代码示例
public class Demo14 {public static void main(String[] args) throws InterruptedException {Object object = new Object();synchronized (object) {System.out.println("wait 之前");// 把 wait 要放到 synchronized 里面来调用. 保证确实是拿到锁了的.object.wait();System.out.println("wait 之后");}}
}
运行结果

此时object就会一直进行wait,当然我们肯定不想让程序一直等待下去,下面将介绍notify()来唤醒它。
notify()
notify 方法是唤醒等待的线程.
方法notify()也要在同步方法或同步块中调用,该方法是用来通知那些可能等待该对象的对象锁的其它线程,对其发出通知notify,并使它们重新获取该对象的对象锁。
如果有多个线程等待,则有线程调度器随机挑选出一个呈 wait 状态的线程。(并没有 "先来后到"),在notify()方法后,当前线程不会马上释放该对象锁,要等到执行notify()方法的线程将程序执行完,也就是退出同步代码块之后才会释放对象锁。
代码示例
public class Demo15 {public static void main(String[] args) {Object object = new Object();Thread t1 = new Thread(() -> {synchronized (object) {System.out.println("wait 之前");try {object.wait();
// object.wait(5000);//也可以指定等待时间后自动唤醒} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("wait 之后");}});Thread t2 = new Thread(() -> {try {Thread.sleep(3000);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized (object) {System.out.println("进行通知");object.notify();}});t1.start();t2.start();}
}
运行结果

notifyAll()
class WaitTask implements Runnable {private Object locker;public WaitTask(Object locker) {this.locker = locker;}@Overridepublic void run() {synchronized (locker) {while (true) {try {System.out.println("wait 开始");locker.wait();System.out.println("wait 结束");} catch (InterruptedException e) {e.printStackTrace();}}}}
}
class NotifyTask implements Runnable {private Object locker;public NotifyTask(Object locker) {this.locker = locker;}@Overridepublic void run() {synchronized (locker) {System.out.println("notify 开始");locker.notifyAll();System.out.println("notify 结束");}}
}public class Demo16 {public static void main(String[] args) throws InterruptedException {Object locker = new Object();Thread t1 = new Thread(new WaitTask(locker));Thread t3 = new Thread(new WaitTask(locker));Thread t4 = new Thread(new WaitTask(locker));Thread t2 = new Thread(new NotifyTask(locker));t1.start();t2.start();t3.start();Thread.sleep(5000);t4.start();}
} 运行结果

注意: 虽然是同时唤醒 3 个线程, 但是这 3 个线程需要竞争锁. 所以并不是同时执行, 而仍然是有先有后的执行.
理解notify()和notifyAll()

notifyAll 一下全都唤醒, 需要这些线程重新竞争锁.

wait和sleep的对比
1. wait 需要搭配 synchronized 使用 . sleep 不需要 .2. wait 是 Object 的方法 sleep 是 Thread 的静态方法 .
相关文章:
Java之线程篇四
目录 volatile关键字 volatile保证内存可见性 代码示例 代码示例2-(volatile) volatile不保证原子性 synchronized保证内存可见性 wait()和notify() wait()方法 notify() 理解notify()和notifyAll() wait和sleep的对比 volatile关键字 volati…...
计算机毕业设计之:基于微信小程序的校园流浪猫收养系统
博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台…...
SpringBoot:关于Redis的配置失效(版本问题)
我们使用redis时发现yaml配置中的redis相关配置不生效,后面发现将配置修改甚至删除所有相关redis的配置,springboot依然能使用redis里面默认的db0并且不报错。上网查阅了一些文章,也都没有解决今天分享下,我的处理方法, SpringBo…...
halcon 快速定义字典
定义一个名为params的字典 Params : dict{} 等价于用 create_dict (Params ) 为字典添加键值对,在halcon中箭只能是字符串,值可以是任何类型的obj或者tuple Params.remove_outer_edges : true Params.max_gap : 150 等价于用 set_dict_object (true,…...
Sublime text3怎么关闭提示更新
问题 sublime text 3有新版本后,会不停地在每次启动后弹窗提示更新版本 第一步 软件安装之前,切记是软件安装之前!!!需要在hosts中添加以下内容(屏蔽官网联网检测):hosts的位置一般在C:\Windows\System32\drivers\etc…...
生成式语言模型技术栈
生成式语言模型的最新技术栈正在快速发展,尤其是随着大规模预训练模型(LLMs)和生成式AI的应用不断扩展。以下是当今最前沿的生成式语言模型技术栈,涵盖从模型开发到优化、推理和部署的各个环节。 1. 基础模型开发 基础模型开发包…...
进程分析工具Process Explorer使用
进程分析工具Process Explorer使用 Process Explorer让使用者能了解看不到的在后台执行的处理程序,能显示目前已经载入哪些模块,分别是正在被哪些程序使用着,还可显示这些程序所调用的DLL进程,以及他们所打开的句柄。Process Expl…...
vue 中如何实现鼠标拖动出发滚动条的跟随移动?
使用场景 在做弹窗、表单或 tab 切换需求的时候,有时候因为内容过长会导致出现滚动条,但是只能拖动滚动条时会导致操作不便,我们会希望实现通过拖动内容区实现滚动条的滑动。这样操作就会简单多了。 实现思路 如果要实现鼠标辅助触发滚动条…...
【Java EE】文件IO
Author:MTingle major:人工智能 --------------------------------------- Build your hopes like a tower! 目录 一、文件是什么? 二、针对文件系统操作的API 1.文件路径,文件名,文件是否存在 2. 创建文件 3.删除文件&#…...
使用 React、Material-UI、Spring、MySQL、MyBatis 以及高德 API 模拟实时位置信息
要使用 React、Material-UI、Spring、MySQL、MyBatis 以及高德 API 模拟实时位置信息,你可以按以下步骤来实现: 目录 1. 前端 (React Material-UI) 2. 后端 (Spring Boot MyBatis MySQL) 3. 模拟实时位置数据 4. 前后端联调 1. 前端 (React Mat…...
UniApp一句话经验: px -> rpx动态转换和动态元素区域的获取
px->rpx转换 在多终端条件下,什么devicePixelRatio,upx2px都是不靠谱的,最直接的是这样: const { screenWidth } uni.getSystemInfoSync()const pixelUnit screenWidth / 750 // rpx->px比例基数 动态元素区域获取 多终…...
Python基于flask框架的智能停车场车位系统 数据可视化分析系统fyfc81
目录 技术栈和环境说明解决的思路具体实现截图系统设计python语言django框架介绍flask框架介绍性能/安全/负载方面可行性分析论证python-flask核心代码部分展示python-django核心代码部分展示技术路线操作可行性详细视频演示源码获取 技术栈和环境说明 结合用户的使用需求&…...
海外服务器哪个速度最快且性能稳定
海外服务器的速度与性能稳定性受多种因素影响,包括地理位置、网络架构、基础设施质量以及用户网络路径等。在众多选择中,几个特定地区的服务器因其卓越表现而备受推崇。 首先,美国硅谷(加利福尼亚州)与纽约的服务器以其技术领先、网络连接稳定…...
C/C++通过CLion2024进行Linux远程开发保姆级教学
目前来说,对Linux远程开发支持相对比较好的也就是Clion和VSCode了,这两个其实对于C和C语言开发都很友好,大可不必过于纠结使用那个,至于VS和QtCreator,前者太过重量级了,后者更是不用说,主要用于…...
工程师 - 如何安装Windows 终端
Windows 终端是一款适用于 Windows 的现代命令行应用程序,支持多个终端会话,包括 Command Prompt、PowerShell 和 Windows Subsystem for Linux (WSL)。它具有标签式界面、可定制的设置(如主题和按键绑定)、改进的文本渲染以及对 …...
UniApp 从Vue2升级为Vue3需要注意哪些方面
Vue官方已经发布了Vue3,Vue2不再维护,也在建议大家都迁移到Vue3,所以Vue2终会被淘汰。 那么UniApp 从Vue2升级为Vue3需要注意哪些方面: 1、main.js 下面请看创建应用实例Vue2与Vue3的不同: Vue2的写法:…...
前端面试CSS常见题目
1. CSS 选择器的优先级 (Specificity) 面试官通常会问你如何计算 CSS 选择器的优先级,这对于避免样式冲突、提高代码可维护性很重要。 优先级计算规则: !important 优先级最高。内联样式(例如:<div style"color: red;&…...
408算法题leetcode--第10天
643. 子数组最大平均数 I 643. 子数组最大平均数 I思路:滑动窗口时间:O(n);空间:O(1) class Solution { public:double findMaxAverage(vector<int>& nums, int k) {double ret 0, temp 0;size_t size nums.size()…...
13年计算机考研408-数据结构
解析: 这个降序链表不影响时间复杂度,因为是链表,所以你想要升序就使用头插法,你想要降序就使用尾插法。 然后我们来分析一下最坏的情况是什么样的。 因为m和n都是两个有序的升序序列。 如果刚好m的最大值小于n的最小值࿰…...
跨平台开发新视角:利用Android WebView实现Web内容的原生体验
在移动应用开发领域,跨平台解决方案一直是一个热门话题。开发者们不断寻求能够同时在iOS和Android平台上提供一致用户体验的方法。而Android的WebView组件,作为一个强大的工具,允许开发者在Android应用中嵌入Web内容,为用户提供接…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
