并发编程-Day2
并发编程
1.共享模型-内存
共享变量在多线程间的<可见性>问题与多条指令执行时的<有序性>问题
1.1Java内存模型
JMM它定义了主存、工作内存抽象概念,底层对应着CPU寄存器、缓存、硬件内存CPU指令优化等.
JMM体现在:
- 原子性-保证指令不会受到线程上下文切换的影响
- 可见性-保证指令不会受cpu缓存的影响
- 有序性-保证指令不会受cpu指令并行优化的影响
1.2可见性
问题:通过变量控制while程序不能够停下来
@Slf4j
public class KeJianXingThreadD2 {static boolean flag = true;public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {while (flag) {}});thread.start();Thread.sleep(3);log.debug("停止thread");flag = false;}
}
分析问题:
- thread从内存读取了flag的值到工作内存中
- thread线程频繁从主内存中读取flag的值,JIT编译器会将flag的值缓存到自己的工作内存中,减少对主内存中flaga的访问,提高效率
- 3秒之后,main线程修改了flag的值,并同步到主内存中,而thread线程一直在读取自己的工作内存的值,一直是旧值,所以线程不会停下来
解决方案:
volatile(关键字)
可以修饰成员变量和静态成员变量,可以避免线程从自己的工作缓存中查找变量,必须到主内存获取它的值,线程操作volatile变量都是直接操作主
public class KeJianXingThreadD2 {volatile static boolean flag = true;public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {while (flag) {}});thread.start();Thread.sleep(3);log.debug("停止thread");flag = false;}
}
只能保证可见性 不能保证原子性
1.3有序性
程序执行的顺序按照代码的先后执顺序执行.
编译器和处理器为了提高执行的效率性能,会对执行进行重排序,指令重排序对单线程应用没有影响,但是在多线程环境下可能出现问题.<重排序的代码没有执行完>
解决:volatile关键字解决
1.4volatile原理
- 读屏障
- 写屏障
2.共享模型-无锁
- CAS与volatile
- 原子整数
- 原子引用
- 原子累加器
- Unsafe
2.1CAS与volatile
/*** @program: springboot-demo-liuan* @description:* @author: Mr.Lh* @create: 2023-03-18 21:29**/
public class CasController {public static void main(String[] args) throws InterruptedException {Acout acout = new Acout(10000);acout.demo(acout);}
}class Acout {public AtomicInteger balance;public Acout(int count) {this.balance = new AtomicInteger(count);}public void with(Integer amout) {while (true) {int i = balance.get();int b = i - amout;if (balance.compareAndSet(i, b)) {break;}}}void demo(Acout acout) throws InterruptedException {for (int i = 0; i < 1000; i++) {new Thread(()->{acout.with(10);}).start();}Thread.sleep(1000);System.out.println(acout.balance.get());}
}
关键点是compareAndSet,它的简称是CAS,它必须是原子性的操作
CAS特点
CAS和volatile可以实现无锁并发,适用于线程数小,多核CPU的场景下
- CAS是基于乐观锁的思想
- synchronized是基于悲观锁的思想
- CAS体现的是无锁并发,无阻塞并发
CAS缺点
- ABA问题:A值变成了B,然后又从B值变回了A,而使用CAS并不会感知到这个情况
- 自旋时间过长:单次CAS并一定能够成功,CAS配合循环来使用
原子整数
- AtomicInteger
- AtomicBoolean
- AtomicLong
原子引用
- AtomicReference(会有ABA的问题)
- AtomicStampedReference(版本号解决ABA的问题)
3.线程池
1.线程池状态
ThreadPoolExecutor 使用 int 的高 3 位来表示线程池状态,低 29 位表示线程数量
状态名 | 高 3 位 | 接收新任务 | 处理阻塞队列任务 | 说明 |
---|---|---|---|---|
RUNNING | 111 | Y | Y | |
SHUTDOWN | 000 | N | Y | 不会接收新任务,但会处理阻塞队列剩余 任务 |
STOP | 001 | N | N | 会中断正在执行的任务,并抛弃阻塞队列 任务 |
TIDYING | 010 | - | - | 任务全执行完毕,活动线程为 0 即将进入 终结 |
TERMINATED | 011 | - | - | 终结状态 |
2.构造方法
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)
- corePoolSize 核心线程数
- maximumPoolSize 最大线程数
- keepAliveTime 生存时间
- unit 生存时间单位
- workQueue 当核心线程数满时,存放的任务队列
- threadFactory 创建线程的工厂
- handler 拒绝策略
四种策略
- CallerRunsPolicy 让调用者运行任务
- DiscardOldestPolicy 放弃队列中最早的任务,本任务取而代之
- AbortPolicy 让调用者抛出异常 默认策略
- DiscardPolicy 放弃本次任务
工厂创建线程
1.newFixedThreadPool
特点:
- 核心线程数==最大线程数,无需超时时间
- 阻塞队列是无界的,可以任意数量的任务
2.newCachedThreadPool
特点:
- 核心线程数是0,最大线程数无限制,60s回收救急线程,救济线程可以无限的创建
- 队列采用的SynchronousQueue 没有容量,没有线程来取是放不进去的
- 没有上限的一个线程池
3.newSingleThreadExecutor
特点
- 线程数固定为1,会放入无界队列中,任务执行完毕,这唯一的线程也不会被释放
任务调度线程池
//延时执行任务
public class TimeExcetor {public static void main(String[] args) {ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);scheduledExecutorService.schedule(() -> {System.out.println("aaaa");}, 2, TimeUnit.MILLISECONDS);scheduledExecutorService.schedule(() -> {System.out.println("bbbbbb");}, 1, TimeUnit.MILLISECONDS);}
}//定时执行任务
@Slf4j
public class TimeExcetor {public static void main(String[] args) {ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);log.debug("start...");pool.scheduleAtFixedRate(() -> {log.debug("running...");}, 1, 1, TimeUnit.SECONDS);}
}
正确处理执行任务异常
-
主动捕获异常
public static void main(String[] args) {ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);scheduledExecutorService.execute(() -> {try {int i = 10 / 0;} catch (Exception ex) {ex.printStackTrace();}System.out.println("aaa");}); }
-
Future
public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService executorService = Executors.newFixedThreadPool(2);Future<Boolean> submit = executorService.submit(() -> {int i = 10 / 0;return true;});//如果任务执行成功则获取值,如果任务失败了 则会打印出异常信息System.out.println(submit.get()); }
4.JUC
4.1 AQS原理
AbstractQueuedSynchronizer,是一个用于实现锁和同步器的基础框架
特点:
- state state 表示同步状态(分独占锁和共享锁) 使用compareAndSetState机制实现加锁
- Node表示队列元素,每个 Node 对象内都保存着当前线程的引用,这些 Node 构成了一个双向队列
4.2ReentrantReadWriteLock
ReentrantReadWriteLock 同样基于 AQS 实现了一套高效的同步机制。它维护着两个锁,一个读取锁和一个写入锁。读取锁允许多个线程同时共享读操作,而写入锁则只允许一个线程进行写入操作。如果有一个线程已经获取了写入锁,那么其他所有线程都无法获得读取或写入锁,它们只能等待写入锁被释放后才能进行读取或写入操作。
4.3Semaphore
是一种在并发编程中经常使用的同步原语。它可以用来管理一组共享的资源,防止共享资源的并发使用。Semaphore包含一个计数器和两个方法:acquire和release
@Slf4j
public class SemaphoreDemo1 {public static void main(String[] args) {Semaphore semaphore = new Semaphore(2);for (int i = 0; i < 10; i++) {new Thread(()->{try {semaphore.acquire();log.info("获取信号量");Thread.sleep(10002);} catch (InterruptedException e) {throw new RuntimeException(e);}finally {semaphore.release();}}).start();}}
}
4.4CountDownLatch
是一个同步工具,它可以让一个线程等待一组操作的完成。CountDownLatch包含一个计数器和两个方法:countDown和await
countDown方法将计数器的值减一,await方法阻塞线程,直到计数器值为零。每次调用countDown方法都会减少计数器的值,当计数器值为零时,await方法会解除所有等待线程的阻塞状态
@Slf4j
public class CountDownLatchDemo1 {public static void main(String[] args) throws InterruptedException {CountDownLatch countDownLatch = new CountDownLatch(3);new Thread(()->{try {Thread.sleep(1000);countDownLatch.countDown();} catch (InterruptedException e) {throw new RuntimeException(e);}}).start();new Thread(()->{try {Thread.sleep(2222);} catch (InterruptedException e) {throw new RuntimeException(e);}countDownLatch.countDown();}).start();new Thread(()->{try {Thread.sleep(3333);} catch (InterruptedException e) {throw new RuntimeException(e);}countDownLatch.countDown();}).start();//主线程阻塞countDownLatch.await();}
}
4.5CyclicBarrier
循环栅栏,用来进行线程协作,等待线程满足某个计数。构造时设置『计数个数』,每个线程执 行到某个需要“同步”的时刻调用 await() 方法进行等待,当等待的线程数满足『计数个数』时,继续执行
public class CyclicBarrierDemo {public static void main(String[] args) {CyclicBarrier cb = new CyclicBarrier(2); // 个数为2时才会继续执行new Thread(()->{System.out.println("线程1开始.."+new Date());try {cb.await(); // 当个数不足时,等待} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}System.out.println("线程1继续向下运行..."+new Date());}).start();new Thread(()->{System.out.println("线程2开始.."+new Date());try { Thread.sleep(2000); } catch (InterruptedException e) { }try {cb.await(); // 2 秒后,线程个数够2,继续运行} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}System.out.println("线程2继续向下运行..."+new Date());}).start();}
}
相关文章:
并发编程-Day2
并发编程 1.共享模型-内存 共享变量在多线程间的<可见性>问题与多条指令执行时的<有序性>问题 1.1Java内存模型 JMM它定义了主存、工作内存抽象概念,底层对应着CPU寄存器、缓存、硬件内存CPU指令优化等. JMM体现在: 原子性-保证指令不会受到线程上…...

第1章 Nginx简介
基于 Nginx版本 1.14.2 ,Tomcat版本 9.0.0 演示 第1章 Nginx简介 1.1 Nginx发展介绍 Nginx (engine x) 是一个高性能的Web服务器和反向代理服务器,也可以作为邮件代理服务器。 Nginx 特点是占有内存少,并发处理能力…...

一个.Net功能强大、易于使用、跨平台开源可视化图表
可视化图表运用是非常广泛的,比如BI系统、报表统计等。但是针对桌面应用的应用,很多报表都是收费的,今天给大家推荐一个免费.Net可视化开源的项目! 项目简介 基于C#开发的功能强大、易于使用、跨平台高质量的可视化图表库&#…...
浅谈 ext2 文件系统的特点、优缺点以及使用场景
ext2(Extended File System 2)是 Linux 中最早的一种文件系统,它是 Linux 文件系统的基础,也被广泛用于其他类 Unix 系统中。下面是 ext2 文件系统的特点、优缺点以及使用场景: 特点: ext2 文件系统可以支…...
Map和Set数据结构和ES6模块化语法
Map和Set数据结构 ●ES6 新增的两种数据结构 ●共同的特点: 不接受重复数据 Set数据结构 ●是一个 类似于 数组的数据结构 ●按照索引排列的数据结构 创建 Set 数据结构 语法: var s new Set([ 数据1, 数据2, 数据3, ... ]) Set 数据结构的属性和方法 ●size 属性 ○语法: 数…...

10_Uboot启动流程_2
目录 _main函数详解 board_init_f函数详解 relocate_code函数详解 relocate_vectors函数详解 board_init_r 函数详解 _main函数详解 在上一章得知会执行_main函数_main函数定义在文件arch/arm/lib/crt0.S 中,函数内容如下: 第76行,设置sp指针为CONFIG_SYS_INIT_SP_ADDR,也…...

python+django汽车4S店零配件保养服务管理系统
汽车4S服务管理系统包括三种用户。管理员、普通员工、客户。 开发语言:Python 框架:django/flask Python版本:python3.7.7 数据库:mysql 数据库工具:Navicat 开发软件:PyCharm django 应用目录结构管…...

STM32F4的输出比较极性和PWM1,PWM2的关系
PWM 输出比较通道 在这里以通用定时器的通道1作为介绍。 如图,左边就是CNT计数器和CCR1第一路的捕获/比较寄存器,它俩进行比较,当CNT>CCR1, 或者CNTCCR1时,就会给输出模式控制器传送一个信号,然后输出模式控制器就…...
易优cms伪静态,EyouCms去除URL中的index.php
针对不同服务器、虚拟空间,运行PHP的环境也有所不同,目前主要分为:Nginx、apache、IIS以及其他服务器。下面分享如何去掉URL上的index.php字符,记得在管理后台清除缓存,对于一些ECS服务器可能要重启nginx等服务! 【Nginx服务器】 在原有的nginx重写文件里新增以下代码片…...

【自然语言处理】【大模型】CodeGeeX:用于代码生成的多语言预训练模型
CodeGeeX:用于代码生成的多语言预训练模型 《CodeGeeX: A Pre-Trained Model for Code Generation with Multilingual Evaluations on HumanEval-X》 论文地址:https://arxiv.org/pdf/2303.17568.pdf 相关博客 【自然语言处理】【大模型】CodeGen&#x…...
Open3D 非线性最小二乘拟合二维多项式曲线
目录 一、算法原理二、代码实现三、结果展示一、算法原理 多项式曲线表示为: p ( x ) = p 1 x n + p 2 x n...
kafka消息队列的两种模式
第一种模式: 点对点模式(一对一,消费者主动拉取数据,消息收到后消息清除) 1.消息生产者生产消息发送给队列,然后消费者从队列中取出并且消费消息 2.消息被消费以后,queue中不再有存储࿰…...

python语法复习
print:输出函数 print(520)效果:输出520. print(hello)效果:输出hello. print(1020)【效果:输出了:1020】注:“ ”在print里面是一个连接符。 print(1020)【效果:输出了30】注: 在此处…...

02-Java基础编程
Java基础编程 Java 基础语法Java 标识符变量变量的类型Java 基本数据类型基本数据类型转换 运算符常见运算符运算符的优先级 程序流程控制分支语句循环结构常用的循环结构循环的嵌套break 和 continue 关键字 数组一维数组多维数组的使用Arrays 工具类的使用数组中常见的异常 J…...
武忠祥老师每日一题||定积分基础训练(十)
已知f(x)连续 ∫ 0 x t f ( x − t ) d t 1 − cos x , 求 ∫ 0 π 2 f ( x ) d x 的值。 \int_{0}^{x}tf(x-t)\,{\rm d}t1-\cos x,求\int_{0}^{\frac{\pi}{2}}f(x)dx的值。 ∫0xtf(x−t)dt1−cosx,求∫02πf(x)dx的值。 已知一个关于f的变上限积分等式,&…...
C/C++趣味程序设计百例(41~50)
C/C语言经典、实用、趣味程序设计编程百例精解(5) 41.马克思手稿中的数学题 马克思手稿中有一道趣味数学问题:有30个人,其中有男人、女人和小孩,在一家饭馆吃饭花了50先令;每个男人花3先令,每个…...
论文阅读-2-DeepSMOTE Fusing Deep Learning and SMOTE for Imbalanced Data
文章目录 Abstract1. Introduction2. Learning From Imbalanced Data1. 数据级2. 算法级3. 集成方法 3. Deep Learning From Imbalanced Data基于深度神经网络的实例生成损失函数适应长尾识别 4. DeepSMOTEA. 动机B. 描述C. encoder-decoder框架D. 增强的损失函数E. 人工图像生…...

三种方法教你让模糊照片秒变高清图
现在随着数字相机和智能手机的普及,我们拍摄的照片数量越来越多,但是有些照片可能因为环境或技术等原因导致模糊不清,这时候我们就需要使用一些软件或工具来让照片变得清晰,以满足我们的需求。 下面介绍三种常用的照片变清晰的方…...

PyTorch深度学习实战 | 基于线性回归、决策树和SVM进行鸢尾花分类
鸢尾花数据集是机器学习领域非常经典的一个分类任务数据集。它的英文名称为Iris Data Set,使用sklearn库可以直接下载并导入该数据集。数据集总共包含150行数据,每一行数据由4个特征值及一个标签组成。标签为三种不同类别的鸢尾花,分别为&…...

服务端接口优化方案
一、背景 针对老项目,去年做了许多降本增效的事情,其中发现最多的就是接口耗时过长的问题,就集中搞了一次接口性能优化。本文将给小伙伴们分享一下接口优化的通用方案。 二、接口优化方案总结 1. 批处理 批量思想:批量操作数据…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...

实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...

9-Oracle 23 ai Vector Search 特性 知识准备
很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…...
k8s从入门到放弃之HPA控制器
k8s从入门到放弃之HPA控制器 Kubernetes中的Horizontal Pod Autoscaler (HPA)控制器是一种用于自动扩展部署、副本集或复制控制器中Pod数量的机制。它可以根据观察到的CPU利用率(或其他自定义指标)来调整这些对象的规模,从而帮助应用程序在负…...