并发编程-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. 批处理 批量思想:批量操作数据…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
9-Oracle 23 ai Vector Search 特性 知识准备
很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…...
数据结构:递归的种类(Types of Recursion)
目录 尾递归(Tail Recursion) 什么是 Loop(循环)? 复杂度分析 头递归(Head Recursion) 树形递归(Tree Recursion) 线性递归(Linear Recursion)…...
