【JavaEE初阶】多线程重点知识以及常考的面试题-多线程进阶(一)
本篇博客给大家带来的是多线程的知识点, .
🐎文章专栏: JavaEE初阶
🚀若有问题 评论区见
❤ 欢迎大家点赞 评论 收藏 分享
如果你不知道分享给谁,那就分享给薯条.
你们的支持是我不断创作的动力 .
王子,公主请阅🚀
- 要开心
- 要快乐
- 顺便进步
- 1. 常见的锁策略
- 1.1 锁策略的相关面试题
- 1.1.1 介绍一下读写锁?
- 1.1.2 说明是自旋锁,为什么要使用自旋锁策略呢? 它的缺点是什么?
- 1.1.3 synchronized 是可重入锁么?
- 2. CAS
- 2.1 什么是CAS
- 2.2 CAS是怎么实现的?
- 2.3 CAS有哪些应用?
- 2.3.1 应用一CAS实现原子类
- 2.3.2 实现自旋锁
- 2.4 CAS的ABA问题
- 2.4.1 什么是ABA问题
- 2.4.2 ABA问题引来的bug
- 2.5 CAS的相关面试题
要开心
要快乐
顺便进步
1. 常见的锁策略
乐观锁与悲观锁
悲观锁:
总是以最坏的情况考虑, 每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样一来如果其他线程想拿到这个数据就会阻塞等待直到拿到锁为止.
乐观锁:
假设数据⼀般情况下不会产生并发冲突,所以在数据进行提交更新的时候,才会正式对数据是否产生并发冲突进行检测,如果发现并发冲突了,则让返回用户错误的信息,让用户决定如何去做。
重量级锁和轻量级锁
锁的核心特性 “原子性”, 这样的机制追根溯源是 CPU 这样的硬件设备提供的.
①CPU 提供了 “原子操作指令”.
②操作系统基于 CPU 的原子指令, 实现了 mutex 互斥锁
③JVM 基于操作系统提供的互斥锁, 实现了 synchronized和ReentrantLock 等关键字和类.
重量级锁:
重量级锁的加锁机制重度依赖了OS提供的mutex.
通常会进行大量的内核用户态切换,很容易引发线程的调度,成本较高.
轻量级锁:
轻量级锁的加锁机制尽可能不使用mutex, 而是尽量在用户态代码完成. 实在不行, 再使用 mutex.
少量的内核态用户态切换,不太容易引发线程调度.
自旋锁和挂起等待锁
自旋锁:
如果获取锁失败, 立即再尝试获取锁, 无限循环, 直到获取到锁为止. 第一次获取锁失败, 第二次的尝试会在极短的时间内到来.一旦锁被其他线程释放, 就能第一时间获取到锁.
优点: 没有放弃 CPU, 不涉及线程阻塞和调度, 一旦锁被释放, 就能第一时间获取到锁.
缺点: 如果锁被其他线程持有的时间比较久, 那么就会持续的消耗 CPU 资源.
挂起等待锁:
如果获取锁失败,不会立即尝试获取锁, 被动等待锁没人用的时候,才能拿到.
优点: 不消耗CPU资源.
缺点: 不能第一时间拿到锁.
公平锁和非公平锁
公平锁:
遵守"先来后到"原则, 当B与C共同竞争同一把锁, B比C先来,B就能就能先于C获取到锁.
非公平锁:
不遵守"先来后到",B和C都有可能获取到锁.
Ⅰ操作系统内部的线程调度就可以视为是随机的. 如果不做任何额外的限制, 锁就是非公平锁. 如果想实现公平锁, 就需要依赖额外的数据结构(队列), 来记录线程的先后顺序.
Ⅱ 公平锁和非公平锁没有好坏之分, 关键还是看适用场景.
可重入锁和不可重入锁
可重入锁:
可重入锁的字面意思是“可以重新进入的锁”,即允许同一个线程多次获取同一把锁。
Java里只要以Reentrant开头命名的锁都是可重入锁,而且JDK提供的所有现成的Lock实现类,包括synchronized关键字锁都是可重入的。而 Linux 系统提供的 mutex 是不可重入锁.
不可重入锁:
一个线程没有释放锁,然后又尝试再次加锁.第二次加锁的时候, 就会阻塞等待. 直到第一次的锁被释放, 才能获取到第二个锁. 但是释放第一个锁也是由该线程来完成, 结果这个线程没有释放第一个锁, 这时候就会死锁.
读写锁
读写锁就是把读操作和写操作区分对待. Java 标准库提供了 ReentrantReadWriteLock 类, 实现了读写锁.
ReentrantReadWriteLock.ReadLock 类表示一个读锁. 这个对象提供了 lock / unlock 方法进行加锁解锁.
• ReentrantReadWriteLock.WriteLock 类表示一个写锁. 这个对象也提供了 lock / unlock方法进行加锁解锁.
其中,
①读加锁和读加锁之间, 不互斥.
②写加锁和写加锁之间, 互斥.
③读加锁和写加锁之间, 互斥.
注意, 只要是涉及到 “互斥”, 就会产生线程的挂起等待. 一旦线程挂起, 再次被唤醒就不知道隔了多久了.因此尽可能减少 “互斥” 的机会, 就是提高效率的重要途径.
synchronized属于哪一种锁?
对于"悲观乐观",是自适应的.
对于"重量轻量",是自适应的.
对于"自旋或者挂起等待",也是自适应的.
synchronized不是读写锁,是可重入锁,也是非公平锁.初始情况下,synchronized会预测当前的锁冲突概率,如果冲突概率不大,此时以乐观锁的模式来运行.(也就是轻量级锁,基于自旋锁的方式实现).
在实际使用过程中,如果发现锁冲突的情况较多,synchronized就会升级成悲观锁(也就是重量级锁,基于挂起等待的方式实现).
1.1 锁策略的相关面试题
1.1.1 介绍一下读写锁?
读写锁就是把读操作和写操作分别进行加锁.
读锁和读锁之间不互斥.
写锁和写锁之间互斥.
写锁和读锁之间互斥.
读写锁最主要用在 “频繁读, 不频繁写” 的场景中.
1.1.2 说明是自旋锁,为什么要使用自旋锁策略呢? 它的缺点是什么?
如果获取锁失败, 立即再尝试获取锁, 无限循环, 直到获取到锁为止. 第一次获取锁失败, 第二次的尝试
会在极短的时间内到来. 一旦锁被其他线程释放, 就能第一时间获取到锁.
相比于挂起等待锁,
优点: 一旦锁被释放就能第一时间获取到锁, 更高效. 在锁持有时间比较短的场景
下非常有用.
缺点: 如果锁的持有时间较长, 就会浪费 CPU 资源.
1.1.3 synchronized 是可重入锁么?
是可重入锁.
可重入锁指的就是连续两次加锁不会导致死锁.
实现的方式是在锁中记录该锁持有的线程身份, 以及一个计数器(记录加锁次数). 如果发现当前加锁的线程就是持有锁的线程则计数器自增.
2. CAS
2.1 什么是CAS
CAS: 全称Compare and swap,字面意思:”比较并交换“,
假设内存中的原数据V,旧的预期值A,需要修改的新值B。CAS(V,A,B); 涉及到以下操作:
① 比较A与V是否相等.(比较)
② 如果比较相等,将B写入V.(交换)
③ 返回操作是否成功.(返回true或者false)
CAS 可以视为是⼀种乐观锁. (或者可以理解成 CAS 是乐观锁的⼀种实现方式)
2.2 CAS是怎么实现的?
针对不同的操作系统,JVM 用到了不同的 CAS 实现原理,简单来讲:
① java 的 CAS 利用的的是 unsafe 这个类提供的 CAS 操作;
② unsafe 的 CAS 依赖了的是 jvm 针对不同的操作系统实现的 Atomic::cmpxchg;
③ Atomic::cmpxchg 的实现使用了汇编的 CAS 操作,并使用 cpu 硬件提供的 lock 机制保证其原子性。
简而言之,是因为有了硬件的支持,软件层面才能实现CAS。
2.3 CAS有哪些应用?
2.3.1 应用一CAS实现原子类
Java标准库中提供
java.util.concurrent.atomic 包, 里面的类都是基于这种方式来实现的.
典型的就是 AtomicInteger 类. 其中的 getAndIncrement 相当于 i++ 操作.
我们来看一下getAndIncrement 的实现过程.
伪代码实现:
class AtomicInteger {private int value;public int getAndIncrement() {int oldValue = value;while ( CAS(value, oldValue, oldValue+1) != true) {oldValue = value;}return oldValue;}
假设两个线程同时调用 getAndIncrement
① 两个线程都读取 value 的值到 oldValue 中. (oldValue 是⼀个局部变量, 在栈上. 每个线程有自己的栈)
② 线程1 先执行 CAS 操作. 由于 oldValue 和 value 的值相同, 直接进行对 value 赋值.
③ 线程2 执行 CAS 操作, 第一次 CAS 的时候发现 oldValue 和 value 不相等, 不能进行赋值. 因此需要进入循环.在循环里重新读取 value 的值赋给 oldValue
④ 接下来线程2 第二次执行 CAS 操作, 此时 oldValue 和 value 相同, 于是直接执行赋值操作
⑤ 线程1 和 线程2 返回各自的 oldValue 的值即可
public class Demo30 {public static AtomicInteger count = new AtomicInteger(0);public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {for (int i = 0; i < 5000; i++) {//count++;count.getAndIncrement();// ++count;//count.incrementAndGet();//count--//count.getAndDecrement();//--count//count.decrementAndGet();}});Thread t2 = new Thread(() -> {for (int i = 0; i < 5000; i++) {//count++;count.getAndIncrement();}});t1.start();t2.start();t1.join();t2.join();System.out.println(count.get());//10000}
}
总结: 前面说的"线程不安全" 本质上是进行自增的过程中穿插执行了. CAS让这里的自增不会穿插执行.核心思路和加锁类似.加锁是通过阻塞的方式避免穿插执行.CAS则是会通过重试的方式避免穿插.
2.3.2 实现自旋锁
自旋锁伪代码:
public class SpinLock {private Thread owner = null;public void lock(){// 通过 CAS 看当前锁是否被某个线程持有. // 如果这个锁已经被别的线程持有, 那么就⾃旋等待. // 如果这个锁没有被别的线程持有, 那么就把 owner 设为当前尝试加锁的线程. while(!CAS(this.owner, null, Thread.currentThread())){}}public void unlock (){this.owner = null;}
}
CAS也是多线程编程的一种重要技巧,虽然实际开发中直接使用CAS的概率不大.但是经常会用到一些内部封装了CAS的操作.
2.4 CAS的ABA问题
2.4.1 什么是ABA问题
假设存在两个线程 t1 和 t2. 有一个共享变量 num, 初始值为 A.
接下来, 线程 t1 想使用 CAS 把 num 值改成 B,
那么就需要①先读取 num 的值, 记录到 oldNum 变量中.
②使用 CAS 判定当前 num 的值是否为 A, 如果为 A, 就修改成 B.
但是, 在 t1 执行这两个操作之前, t2 线程可能把 num 的值从 A 改成了B, 又从 B 改成了 A.
线程t1的CAS默认num不变就修改.但是num的值已经被 t2 给改了.只不过又改回A了. 这个时候 t1 是否要更新num的值为 B呢?
关键的问题是, t1 线程无法区分当前这个变量始终是 A, 还是经历了一个变化过程.
2.4.2 ABA问题引来的bug
大部分情况下,t2 线程这样的一个反复横跳的改动,对于t1 是否修改num是没有影响的. 但是不排除一些特殊情况.
假设 小丑老哥 有 100 存款. 小丑想从 ATM 取 50 块钱. 取款机创建了两个线程, 并发的来执行 -50 操作.
我们期望一个线程执行 -50 成功, 另一个线程 -50 失败.
如果使用 CAS 的方式来完成这个扣款过程就可能出现问题.
正常的过程
① 存款 100. 线程1 获取到当前存款值为 100, 期望更新为 50; 线程2 获取到当前存款值为 100, 期望更新为 50.
② 线程1 执行扣款成功, 存款被改成 50. 线程2 阻塞等待中.
③ 轮到线程2 执行了, 发现当前存款为 50, 和之前读到的 100 不相同, 执行失败.
异常的过程
① 存款 100. 线程1 获取到当前存款值为 100, 期望更新为 50; 线程2 获取到当前存款值为 100, 期望更新为 50.
② 线程1 执行扣款成功, 存款被改成 50. 线程2 阻塞等待中.
③ 在线程2 执行之前, 小丑的朋友滑稽正好给小丑转账 50, 账户余额变成 100 !!
④ 轮到线程2 执行了, 发现当前存款为 100, 和之前读到的 100 相同, 再次执行扣款操作.
这个时候, 扣款操作被执行了两次!!! 都是 ABA 问题导致的!!
解决方案:
给要修改的值,引入版本号. 在 CAS 比较数据当前值和旧值的同时, 也要比较版本号是否符合预期.
CAS 操作在读取旧值的同时, 也要读取版本号.
真正修改的时候,
① 如果当前版本号和读到的版本号相同,则修改数据,并把版本号+1.
② 如果当前版本号高于读到的版本号.就操作失败(认为数据已经被修改过了)
2.5 CAS的相关面试题
1. 讲解一下自己理解的CAS机制
全称 Compare and swap, 即 “比较并交换”. 相当于通过⼀个原子的操作, 同时完成 “读取内存, 比较是
否相等, 修改内存” 这三个步骤. 本质上需要 CPU 指令的支撑.
2. ABA问题怎么解决?
给要修改的数据引入版本号. 在 CAS 比较数据当前值和旧值的同时, 也要比较版本号是否符合预期. 如
果发现当前版本号和之前读到的版本号一致, 就真正执行修改操作, 并让版本号自增; 如果发现当前版
本号比之前读到的版本号大, 就认为操作失败.
本篇博客到这里就结束啦, 感谢观看 ❤❤❤
🐎期待与你的下一次相遇😊😊😊
相关文章:
【JavaEE初阶】多线程重点知识以及常考的面试题-多线程进阶(一)
本篇博客给大家带来的是多线程的知识点, . 🐎文章专栏: JavaEE初阶 🚀若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 . 王子,公主请阅🚀 要开心要快乐顺便进步 1. 常…...
计算机视觉图像分割入门:阈值、区域生长与分水岭算法
计算机视觉图像分割入门:阈值、区域生长与分水岭算法 一、前言二、图像分割基础概念大揭秘2.1 图像分割的定义2.2 图像分割的目的与作用2.3 图像分割的应用领域三、阈值算法:最简单的图像分割法3.1 原理剖析3.2 手动阈值分割及代码示例3.3 自动阈值分割方法及代…...
android弱网环境数据丢失解决方案(3万字长文)
在移动互联网时代,Android 应用已经成为人们日常生活中不可或缺的一部分。从社交媒体到在线购物,从移动办公到娱乐游戏,用户对应用的依赖程度与日俱增。然而,尽管网络基础设施在全球范围内得到了显著改善,弱网环境依然…...
设计模式:迪米特法则 - 最少依赖,实现高内聚低耦合
一、迪米特法则简介 迪米特法则(Law of Demeter,简称 LoD),也称为“最少知识法则”,核心思想是:一个对象应当对其他对象有最少的了解,仅与直接相关的对象交互。通过减少对象之间的耦合度&#…...
React 把一系列 state 更新加入队列
把一系列 state 更新加入队列 设置组件 state 会把一次重新渲染加入队列。但有时你可能会希望在下次渲染加入队列之前对 state 的值执行多次操作。为此,了解 React 如何批量更新 state 会很有帮助。 开发环境:Reacttsantd 学习内容 什么是“批处理”以…...
AntVG2可视化学习与开发笔记-React19(持续更新)
目录 开始工作 第一步:创建画布空间 第二步:获取画布空间并挂载AntVG2 第三步:进行画布设计配置与数据挂载 第四步:完整代码 实际效果如下 参数理解 一、scale 1. 归一化range:[0,1] 2.nice、domainMin 开始工作 第一…...
从PPT到DeepSeek开启信息可视化的全新之旅
在当今信息爆炸的时代,如何高效、生动地展示信息成为了个人与企业在沟通、汇报、推广等场景中面临的关键挑战。传统的演示工具,如PPT,虽然曾经是展示信息的主力军,但随着技术的发展和人们审美、交互需求的提升,其局限性…...
spark-sql学习内容总结
SparkSession 定义与功能:SparkSession是Spark SQL的入口,封装SparkContext,提供了创建DataFrame和执行SQL的能力。它实质上是SQLContext和HiveContext的组合,因此兼容这两者的API。 创建方式:在使用spark-shell…...
Spring-AI-alibaba 结构化输出
1、将模型响应转换为 ActorsFilms 对象实例: ActorsFilms package com.alibaba.cloud.ai.example.chat.openai.entity;import java.util.List;public record ActorsFilms(String actor, List<String> movies) { } GetMapping("/toBean")public Ac…...
ffmpeg实现视频转码
ffmpeg 实现视频转码 什么是视频编码 视频上传成功后需要对视频进行转码处理。 什么是视频编码? 查阅百度百科如下: 所谓视频编码方式就是指通过压缩技术,将原始视频格式的文件转换成另一种视频格式文件的方式。视频流传输中最为重要的编解…...
【Java学习笔记】Java初级阶段代码规范
Java 初级阶段代码规范 1. 类、方法的注释,要以 javadoc 的方式来写。 2. 非 Java Doc 的注释,往往是给代码的维护者看的,着重告读者为什么这样写,如何修改,注重什么问题等 3. 使用 tab 操作,实现缩进&am…...
适应 AI 时代的软件开发流程:用 AI + TDD 构建可维护项目
🧠 适应 AI 时代的软件开发流程:用 AI + TDD 构建可维护项目 本文面向有系统开发经验的工程师,分享如何结合 Git 管理、AI 协作、YAML 驱动与 TDD 开发方式,高效构建一个可维护、可协作、可交付的嵌入式或通用工程项目。适合 BLE 模块、协议栈组件、物联网控制系统等项目落…...
EasyCVR视频汇聚系统:AIoT+视频智能分析赋能食品安全生产全流程监管
近年来,随着食品安全问题频发,消费者对食品加工企业的信任度逐渐下降,企业生产监管难度加大,市场监管也面临诸多挑战。在这样的背景下,食品加工企业迫切需要通过智能化手段提升生产管理水平,满足消费者和监管部门的要求,同时实现自身业绩的提升。 本文将结合EasyCVR与智…...
ASP.NET Core 性能优化:分布式缓存
文章目录 前言一、分布式缓存的核心概念作用:与内存缓存的区别: 二、ASP.NET Core 中的 IDistributedCache三、常用分布式缓存实现1)Redis(最常用)2)SQL Server3)NCache(企业级方案&…...
一款安全好用的企业即时通讯平台,支持统一门户
在数字化转型的浪潮中,企业面临着信息孤岛、系统分散、协作低效等诸多挑战。BeeWorks作为一款专为企业打造的数字化底座平台,凭借其强大的企业内部应用集成能力和单点登录功能,正在成为企业数字化转型的有力推手。 数字化底座平台࿱…...
C语言 栈 的 描述 和 详解
什么是栈? 栈是一种特殊的线性数据结构。 定义及特点 - 栈是一种只能在一端进行插入和删除操作的特殊线性表。它按照后进先出(Last In First Out,LIFO)的原则存储数据,就像一个只能从顶部取放物品的箱子,…...
.NET MCP 示例
服务器端示例 基础服务器 以下是一个基础的 MCP 服务器示例,它使用标准输入输出(stdio)作为传输方式,并实现了一个简单的回显工具: using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.H…...
【论文阅读】MOE奠基论文《Adaptive Mixtures of Local Experts》
《Adaptive Mixtures of Local Experts》 前言一、让协同学习竞争1.1 方案1.2 方案演变的由来 二、让竞争学习协同2.1 竞争学习2.2 竞争学习协同 三、案例验证3.1 任务背景3.2 实验结果3.3 后续工作 (Future Work) 前言 论文提出了一个基于多个分离网络的有监督学习方案,该方案…...
MATLAB中replace函数用法
目录 语法 说明 示例 替换字符串数组中的子字符串 替换匹配模式的子字符串 替换多个子字符串 replace函数的功能是查找并替换一个或多个子字符串。 语法 newStr replace(str,old,new) 说明 newStr replace(str,old,new) 将所有出现的子字符串 old 替换为 new。如果 …...
MATLAB基本数据类型
1. 数值类型 整数类型: 有符号整数(如 int8, int16, int32, int64)和无符号整数(如 uint8, uint16, uint32, uint64)。 这些类型分别占用 1、2、4、8 个字节,表示不同范围的整数值。 浮点数类…...
LeetCode 热题 100_单词拆分(86_139_中等_C++)(动态规划)
LeetCode 热题 100_单词拆分(86_139) 题目描述:输入输出样例:题解:解题思路:思路一(动态规划): 代码实现代码实现(思路一(动态规划)&a…...
Spring Boot 集成spring-boot-starter-data-elasticsearch
第一步,添加Maven依赖 <!--es--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency> 第二步,配置yml spring:elastic…...
【Linux】Linux下的gcc/g++编译器与动静态库
目录 对程序的认知&&初识gcc逐步分析程序的编译步骤预编译【进行宏替换】gcc需要执行的指令 ⭐ 编译【C语言——>汇编语言】gcc要执行的指令⭐ 汇编【汇编语言——>可重定位目标二进制文件】gcc需要执行的指令 链接【生成可执行文件或库文件】gcc需要执行的指令 …...
从暴力到动态规划再到双指针:使用 Java 探索接雨水问题的不同解法
文章目录 一、问题描述二、暴力法(Brute Force)思路实现代码 三、动态规划法(Dynamic Programming)思路实现代码 四、双指针法(Two Pointers)思路实现代码 五、方法对比 在本文中,我们将探讨经典…...
CI/CD(十) Jenkins共享库与k8s集成
一、创建k8skey(v1.28.2版本) 1、查看k8s集群名称 rootk8s-master:~# kubectl config get-contexts CURRENT NAME CLUSTER AUTHINFO NAMESPACE * kubernetes-adminkubernetes kubernetes kuber…...
5.Elasticsearch - Spring Data 框架
一、Kibana 介绍 Kibana 是一个免费且开放的用户界面,能够让你对 Elasticsearch 数据进行可视化,并让你在 Elastic Stack 中进行导航。你可以进行各种操作,从跟踪查询负载,到理解请求如何流经你的整个应用,都能轻松完…...
如何通过技术手段降低开发成本
通过技术手段降低开发成本的关键在于: 自动化工具的使用、优化开发流程、云计算资源的利用、开发技术栈的精简与创新、团队协作平台的高效管理。 其中,自动化工具的使用是最为有效的技术手段之一。自动化工具通过减少人工干预和重复性工作,大…...
java android持久化数据
1. SQLite 数据库(Android 内置) 1.1 创建数据库帮助类 public class DatabaseHelper extends SQLiteOpenHelper {private static final String DATABASE_NAME "MyDatabase.db";private static final int DATABASE_VERSION 1;// 表名和列名…...
Chromium 134 编译指南 macOS篇:系统环境准备(一)
1. 引言 在当今浏览器领域,开源项目Chromium的地位举足轻重。作为众多现代浏览器的技术基础,Chromium不仅驱动着Google Chrome,还为Microsoft Edge、Opera等众多知名浏览器提供了核心引擎。对于热衷于浏览器技术研究,或希望开发自…...
性能优化-Spring参数配置、数据库连接参数配置、JVM调优
SpringBoot配置参数 server:tomcat:#线程池配置max-threads: 200 # 最大工作线程数(建议:2~4倍CPU核心数,如16核设200-400)min-spare-threads: 20 # 最小空闲线程(应对突发流量,…...
【2025年泰迪杯数据挖掘挑战赛】B题 数据预处理+问题建模与求解
目录 2025年泰迪杯数据挖掘挑战赛 B题数据预处理 问题一、二建模与求解三、数据预处理3.1 基于多核并行的协同处理方法的数据读取3.2 基于多核并行协同处理的数据聚合 四、问题一五、问题一技术文档与matlab代码 2025年泰迪杯数据挖掘挑战赛 B题 数据预处理 问题一、二建模与求…...
git怎么使远程分支回退到指定的节点处
git使远程分支回退到指定的节点 引言场景描述步骤 引言 最近提交代码的时候,总将分支合并错,原本要合到A分支,结果合并到了B分支,这样就导致b分支需要回退到我没有合并之前的节点处。 本文记录下怎么将远程分支回退到指定的节点。…...
Spring Boot 使用 QQ 企业邮箱发送邮件的完整指南(含 535 错误排查)
在 Spring Boot 项目中集成邮件功能非常常见,尤其是用户注册通知、异常报警、定期报告等场景。但如果你使用的是 QQ 企业邮箱(smtp.exmail.qq.com),可能会遇到如下典型错误: 535 Error: authentication failed, system busy这篇博客将详细解析出现该问题的原因、排查路径…...
MySQL联合查询||多表查询
mysql中如何注释...
java 递归遍历JSON字符串获取某个字段的值
在 Java 中,若要递归遍历 JSON 字符串并获取特定字段的值,可借助 Jackson 库。以下是一个示例代码,它能实现递归遍历 JSON 字符串并获取指定字段的值。 import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.data…...
OceanBase4.0社区版 单机快速部署
以下内容结合OceanBase官方文档进行安装部署测试 官方文档地址:https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000002012693 一.部署方式 OceanBase 企业版: • 使用 OCP 部署 OceanBase 集群 • 使用 OBD 部署 OceanBase 集群 •…...
CExercise_05_1伪随机数_2编写程序模拟掷骰子的游戏(每一次投掷,都投掷两个骰子)
题目: 编写程序模拟掷骰子的游戏(每一次投掷,都投掷两个骰子)。每局游戏的规则如下: 第一次掷的时候: 如果点数之和为 7 或 11 则获胜; 如果点数之和为2、3或12则落败; 其他情况下的…...
【更新至2023年】2000-2023年中国气候政策不确定性指数(全国、省、市三个层面)
【更新至2023年】2000-2023年中国气候政策不确定性指数(全国、省、市三个层面) 1.时间:2000-2023年 2.来源:使用人工审计和深度学习算法MacBERT模型,基于中国《人民日报》《光明日报》《经济日报》《环球时报》《科技…...
机器学习中 提到的张量是什么?
在机器学习中, 张量(Tensor) 是一个核心数学概念,用于表示和操作多维数据。以下是关于张量的详细解析: 一、数学定义与本质 张量在数学和物理学中的定义具有多重视角: 多维数组视角 传统数学和物理学中,张量被定义为多维数组,其分量在坐标变换时遵循协变或逆变规则。例…...
【Python爬虫】简单案例介绍3
本文继续接着我的上一篇博客【Python爬虫】简单案例介绍2-CSDN博客 目录 3.3 代码开发 3.3 代码开发 编写代码的步骤: request请求科普中国网站地址url,解析得到类名为"list-block"的div标签。 for循环遍历这个div列表里的每个div࿰…...
对于客户端数据存储方案——SQLite的思考
SQLite 比较适合进行本地小型数据的存储,在功能丰富性和并发能力上不如 MySQL。 数据类型差异 SQLite 使用动态类型系统:只有 5 种基本存储类 (NULL, INTEGER, REAL, TEXT, BLOB) 类型亲和性:SQLite 会将声明的列类型映射到最接近的存储类 …...
基于Nacos+动态线程池的分布式系统弹性设计:投行交易与风控场景实战
业务痛点和需求分析 在投行高频交易系统和对公贷款风控计算引擎中,我们面临两大核心挑战: 流量洪峰波动剧烈 交易时段TPS可达10万/秒,非交易时段下降80%风控模型计算存在突发性批量任务(如月末集中评审) 架构设计与…...
高并发内存池(定长内存池基础)
定长内存池的设计 定长内存池定长内存池的原理讲解代码实现定义对象New对象的主要逻辑delete对象的主要逻辑完整代码 定长内存池 为什么我们要设计这个定长内存池呢?首先malloc是c标准库中向堆申请空间的接口,变相的说malloc是普遍性,而我们…...
element-ui plus 中 filter-method 函数多次触发问题解决
前情提要 点进这个文章的小伙伴,应该都是为了解决一个需求,把原本的前端过滤改为后端过滤,但是将filter-method修改为后端取数据后,发现其触发了很多次。博主也是在修改表格过滤时用到了这个坑,本篇文章为大家解决一下…...
物联网场景实战:智能电表数据管理与分析(一)
智能电表与物联网的融合 在当今数字化时代,随着物联网(IoT)技术的飞速发展,各行业都在积极探索如何利用这一技术实现转型升级 。电力行业也不例外,智能电表作为电力系统与物联网融合的关键节点,正发挥着越来…...
网络中的基本概念
这篇文章主要介绍我们在学习网络的过程中,会碰到的一系名词,对其概念进行解释,让大家知道这些都是干什么的。 网络:若干个节点和连接这些节点的链路组成的,用于实现信息交换资源共享。 节点:网络中各种接地…...
行锁(Row Locking)和MVCC(多版本并发控制)
在数据库系统中,**行锁(Row Locking)和MVCC(多版本并发控制)**是两种不同的并发控制机制,它们的使用场景和原理有显著区别。以下是详细对比和适用场景分析: 一、行锁(Row Locking&am…...
AlexNet神经网络详解及VGGNet模型和
AlexNet模型细节 一共8层,5个卷积层,3个全连接层 AlexNet工程技巧 多GPU训练,ReLU激活函数,LRN归一化,Dropout,重叠池化,数据增强等 多GPU训练 除了将模型的神经元进行了并行,还使…...
【Linux网络】Socket 编程TCP
🌈个人主页:秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343 🔥 系列专栏:https://blog.csdn.net/qinjh_/category_12891150.html 目录 TCP socket API 详解 socket(): bind(): listen(): accept(): connect V0…...
代码训练day27贪心算法p1
贪心的本质是选择每一阶段的局部最优,从而达到全局最优 贪心算法一般分为如下四步: 将问题分解为若干个子问题找出适合的贪心策略求解每一个子问题的最优解将局部最优解堆叠成全局最优解 1.分发饼干 先将饼干数组和小孩数组排序。 然后从后向前遍历…...