【Java ee 初阶】多线程(8)
Synchronized优化:
一、锁升级
锁升级时一个自适应的过程,自适应的过程如下:
在Java编程中,有一部分的人不一定能正确地使用锁,因此,Java的设计者为了让大家使用锁的门槛更低,就在synchronized中引入了很多优化策略。
*首先,根据前面的学习,我们已经初步了解了自旋锁和重量级锁,那么图中的偏向锁是什么?
偏向锁,不是真正加锁,而只是做个标记,如果整个过程中,没有其他线程来竞争这个锁,偏向锁状态就始终保持,直到最终解锁。但是,如果在过程中,遇到其他线程也尝试来竞争这个锁,就可以在其他线程拿到锁之前,抢先获取这个锁。这样子仍然可以使其他线程产生阻塞,保证线程的安全。
锁升级的过程:
1.偏向锁->轻量级锁:说明该线程上发生了锁竞争
2.轻量级锁->偏向锁:竞争更加激烈
那我们如何去了解竞争的激烈程度呢?——JVM内部,统计了这个锁上面有多少个线程在等待获取,这一切都取决于JVM的实现。
而我们作为程序员,关心的是策略,而不是参数,因为参数都是可以调整的,但是策略是不变的。
锁升级,对于当前主流的JVM实现来说,是“不可逆”的,一旦升级了,就无法回头降级了
二、锁消除
有些代码,那你写了加锁,但是在JVM执行的时候会发现,这个地方没必要加锁,因此JVM就会自动把锁给去除掉
例如:我们知道,StringBuilder不带有synchronized,StringBuffer带有synchronized,因此可能有人在单线程环境下就使用StringBuffer,此时这个锁只在一个线程中,因此会被JVM给优化掉。
JVM的优化是一方面,咱们作为程序员,也不能够完全摆烂。
三、锁粗化
首先我们先了解一个概念——锁的粒度。加锁和解锁范围中代码越多,锁的粒度就越粗,反之锁的粒度就越细
如图我们可知这两段代码,上面那一段代码的粒度更粗,下面代码的粒度更细。
获取到一次锁,可能是一件不太容易的事情。因此有的时候,JVM会进行锁粗化,将加锁解锁的次数减少,以此提高效率。synchronized关键字,作为Java的关键字,底层实现是在JVM内部完成的,不是通过Java来实现的,而是通过C++来实现的。
总结:synchronized优化主要体现在:
1.锁升级
2.锁消除
3.锁粗化
四、CAS
CAS,全称compare and swap,比较和交换。
这是一串cas的伪代码(不是严格符合语法等待,知识用来描述一下逻辑)
address:是一个内存地址
expectValue,swapValue:是CPU寄存器
这段代码实现的内容是:拿着内存中的值,和寄存器1的值进行比较,如果二者相等,就把内存和寄存器2的值进行交换。一般来说,只关心内存中值的变化,而不关心寄存器2中发生了什么变化。上述的交换,也可以近似理解成赋值。
注意,上述所有的逻辑,都是通过“一个CPU指令”完成的。一条指令,意味着这是原子的!!没有线程安全的问题。
CPU的特殊指令完成了上述的所有操作—>操作系统封装了这个指令,形成了一个系统的API—>Java中又封装了操作系统的API,由unsafe包进行提供,这里提供的操作,比较底层,可能不安全。
CAS的典型应用
1.实现原子类
可以将原来的三步打包成原子的,通过AtomicInteger,原子的进行++ -- 等操作
例如:
package Thread;public class demo1 {public static int count = 0;
public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(()->{for(int i=0;i<5000;i++){count++;}});Thread t2 = new Thread(()->{for(int i=0;i<5000;i++){count++;}});t1.start();t2.start();t1.join();t2.join();System.out.println(count);
}}
输出结果:
出现了运算符重载的问题!
什么是运算符重载:运算符重载就是让已有的运算符针对不同的类,也能够有对应的效果,Java并不支持。运算符重载的好处,就是可以用使代码的一致性更高,比如,定义一个类,“复数”通过运算符重载,就可以使得复数类和其他的数字类型相似,都可以进行加减乘除。定义一个矩阵类也可以通过运算符重载。
Java中认为,上述写法,容易被滥用,因此Java并不支持。
package Thread;import java.util.concurrent.atomic.AtomicInteger;public class demo1 {private 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.getAndIncrement();//count++//count.incrementAndGet();//++count//count.getAndIncrement();//count++//count.getAndDecrement();//--count//count.GetAndDecrement();//count--//count.getAndAdd(10);//count+=10;}});Thread t2 = new Thread(()->{for(int i=0;i<5000;i++){count.getAndIncrement();//count++}});t1.start();t2.start();t1.join();t2.join();System.out.println(count);
}}
此时的输出:
这样的操作,不仅线程安全,而且效率更高,不涉及到阻塞。因此在实际开发中,如果有这种计数的需求,优先考虑原子类,而不是自己去加锁。
划红线的部分,就是JVM封装过的,比上述谈到的CAS还要更加复杂一点,但是他们的本质是一样的。
伪代码实现:
CAS如果一样,就说明在这两者之前没有其他线程修改value内存,此时就可以安全的对value进行修改了。如果CAS发现有其他线程插队,就会进入循环,重新load。此处的oldValue是寄存器,而不是变量。C语言曾经能够定义寄存器变量,但是后来也废除的,也就只有汇编能够直接操作寄存器了,和之前传统的++相比,在真正进行修改之前,又做了判定。
2.实现自旋锁
CAS实现自旋锁的伪代码
如果owner为null,解锁状态,否则就会保存持有锁的线程的引用。如果锁已经被占用了,这个循环,就会快速地反复地循环。循环体中是没有任何sleep。这是一种消耗cpu,换来尽快地加锁速度。但是,如果锁竞争很激烈,大量的线程都会这样自旋,就会消耗非常多的cpu,那么cpu就负担不起了,锁释放之后,这些线程还是要竞争,还是意味着大量的线程是无法第一时间拿到锁的。
下面的赋值操作天然就是原子的,判定-赋值(check and set),典型的非原子的操作。
CAS的ABA问题
通过CAS来判定,当前load到寄存器的内容和内存的内容是否一致,如果一致,就认为没有其他线程修改过这个变量,接下来本线程的修改就是安全的。
然而,这里面存在着一个缺陷:可能出现这种情况:另一个线程又把内存的值从A改成B,又从B改回了A,此时CAS是感知不到的,仍然会认为没有其他线程修改过的。
ABA问题,通常情况下都是没事的,即使其他线程真的修改了,由于又修改回了原来的值,所以ABA现象不一定给程序引起BUG,但是如果遇到特别极端的场景,那还是有可能的,下面是一个非常极端的例子:
上述场景下,由于ABA问题,导致了重复扣款。
那么,针对ABA问题,我们应该如何解决呢?上述问题之所以出现ABA问题,是因为他针对余额的修改可能加,也可能减,如果改变成“只能加,不能减”,那么就可以解决上述问题。因此,我们引入版本号,约定每次修改,都需要对版本号+1,并且每次CAS比较的时候都是比较版本号是否相同(相同的话,进行版本号+1 和 余额修改)
我们可以定义一个类,包含版本号和余额,如下:
五、Callable接口
callable接口,类似于Runnable,也是属于JUC(java.util.concurrent)这个包的。call自定义返回值,run返回值是void。
接下来让我们利用Callable接口创建一个线程,并且通过这个线程计算1+2+3+...+100
package Thread;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class demo2 {
public static void main(String[] args) throws InterruptedException, ExecutionException {//callable 带有泛型参数 泛型参数就是返回值类型Callable<Integer> callable = new Callable<Integer>() {@Overridepublic Integer call() throws Exception {int result = 0;for(int i=0;i<=100;i++){result+=i;};return result;};};FutureTask<Integer> futureTask = new FutureTask<>(callable);Thread t = new Thread(futureTask);t.start();//get会阻塞等待线程执行完毕,拿到返回值System.out.println(futureTask.get());
}
}
创建线程的方式:1.继承Thread 2.实现Runnable 3.基于lambda(本质还是Runnable)4.实现Callable 5.基于线程池
六、ReentranLock
ReentrantLock是一把比较传统的锁,在synchronized还不成熟的时候,这个锁就是进行多线程编程加锁的主要方案
package Thread;import java.util.concurrent.locks.ReentrantLock;public class demo3 {private static int count = 0;public static void main(String[] args) throws InterruptedException {ReentrantLock locker = new ReentrantLock();Thread t1 = new Thread(()->{for(int i=0;i<5000;i++){//加锁locker.lock();count++;//解锁locker.unlock();}});Thread t2 = new Thread(()->{for(int i=0;i<5000;i++){locker.lock();count++;locker.unlock();} });t1.start();t2.start();t1.join();t2.join();System.out.println(count);}}
这种写法,容易把unlock遗漏
换成这种写法,不太美观
区别与联系
1.synchronized是一个关键字,是JVM内部实现的(大概率是基于C++实现)
ReentrantLock是标准库的一个类,在JVM外实现的(基于Java实现的)
2.synchronized使用的时候不需要手动释放锁
ReentantLock使用的时候需要手动释放,使用的时候更加灵活,但是也容易遗漏。
3.synchronized是非公平锁,ReentrantLock默认是非公平锁,可以通过构造方法传入一个true开启公平锁模式
4.synchronized在申请锁失败的时候会死等,ReentrantLock可以通过trylock的方式等待一段时间就放弃(这是synchronized不具备的特点,trylock加锁失败的时候会直接放弃)
5.ReentrantLock拥有更强大的唤醒机制,synchronized是通过Object的wait /notify实现 等待-唤醒。每次唤醒的是一个随机等待的线程 ReentrantLock搭配Condition类来实现等待-唤醒,九二一更加精确控制唤醒某个指定的线程
相关文章:
【Java ee 初阶】多线程(8)
Synchronized优化: 一、锁升级 锁升级时一个自适应的过程,自适应的过程如下: 在Java编程中,有一部分的人不一定能正确地使用锁,因此,Java的设计者为了让大家使用锁的门槛更低,就在synchronize…...
数字孪生大屏UI设计
近年来,5G、大数据、云计算等新一代信息技术的蓬勃发展,计算机仿真技术与拟真软件的成熟运用,让数字孪生技术开始蔓延渗透到“互联网”相关的产业中。数字孪生大屏给予了可视化的数据直观窗口,其中展现的动态映射与实时数据让业务流转效率得到了有效提升,管理、运营和决策都能高…...
【Java ee 初阶】多线程(9)上
一、信号量Semaphore 本质上就是一个计数器,描述了一种“可用资源”的个数 申请资源(P操作):使得计数器-1 释放资源(V操作):使得计数器1 如果计数器为0了,继续申请资源ÿ…...
eclipse开发环境中缺少JavaEE组件如何安装
新版本eclipse去掉server了吗?在最近新版本的eclipse里面,确实找不到server模块了,无法配置tomcat等web服务器插件了。我们需要自己手工安装一下javaEE组件才行。 1 1:找到自己当前eclipse版本号码 2:去这个地址&…...
stm32之ADC
目录 1.简介2.逐次逼近型ADC3.基本结构4.输入通道5.转换模式6.触发控制7.数据对齐8.转换时间7.校准10.ADC外围电路11.api和结构体11.1 结构体11.2 api1. ADC_DeInit2. ADC_Init3. ADC_StructInit4. ADC_Cmd5. ADC_DMACmd6. ADC_ITConfig7. ADC_ResetCalibration8. ADC_GetReset…...
从电话到V信语音:一款App实现全场景社交脱身
作为一名资深社恐人士,我深知那些无法脱身的社交场合有多煎熬。上周参加一个行业聚会,面对滔滔不绝的陌生人,我如坐针毡却又找不到合适的离场理由。这时我突然想起之前朋友推荐的一款神器应用,它让我得以优雅脱身。今天就来分享这…...
conda init before conda activate
先conda init 然后退出命令窗口,再重新打开命令窗口再conda activate...
MySQL数据库高可用(MHA)详细方案与部署教程
一:MHA简介 核心功能 二:MHA工作原理 三:MHA组件 四:MHA 架构与工具 MHA架构 Manager关键工具 Node工具 五:工作原理与流程 1: 故障检测 2: 故障切换(Failover) 3 : 切换模式 六&a…...
《Python星球日记》 第44天: 线性回归与逻辑回归
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏:《Python星球日记》,限时特价订阅中ing 目录 一、引言:回归方法的重要性二、线性回归原理与损失函数1. 线性回归的数学模型2. 损失函数:衡量…...
Flutter TabBar / TabBarView 详解
目录 一、引言 二、基本用法 代码解析 三、主要属性 3.1 TabBar 3.2 TabBarView 四、进阶定制:突破默认样式 4.1 视觉样式深度定制 4.2 自定义指示器与标签 4.3 动态标签管理 五、工程实践关键技巧 5.1 性能优化方案 5.2 复杂手势处理 5.3 响应式布局…...
001 环境搭建
🦄 个人主页: 小米里的大麦-CSDN博客 🎏 所属专栏: Linux_小米里的大麦的博客-CSDN博客 🎁 GitHub主页: 小米里的大麦的 GitHub ⚙️ 操作环境: Visual Studio 2022 文章目录 Linux 环境搭建全解析:从历史到实践一、Linux 的起源与…...
Spark-core-RDD入门
RDD基本概念 Resilient Distributed Dataset 叫做弹性分布式数据集,是Spark中最基本的数据抽象,是分布式计算的实现载体,代表一个不可变,可分区,里面的元素并行计算的集合。 - Dataset: 一个数据集合&…...
在scala中,转换算子和行动算子有什么区别
在Scala结合Spark编程中,转换算子(Transformation)和行动算子(Action)有以下区别: 执行机制 **转换算子**: 具有惰性求值(延迟计算)特性 。它对RDD(弹性分布…...
六级阅读---2024.12 卷一 仔细阅读1
文章 Imagine youre an alien sent to Earth to document the behaviour of the mammals inhabiting the planet. You stumble into a movie theatre thats showing the latest Hollywood horror film. Several dozen humans are gathered together in a dark, undercoated r…...
驱动开发硬核特训 · 专题篇:Vivante GPU 与 DRM 图形显示体系全解析(i.MX8MP 平台实战)
视频教程请关注 B 站:“嵌入式Jerry”。 一、背景导读:GPU 与 DRM 到底谁负责“显示”? 在嵌入式 Linux 图形系统中,“画面怎么显示出来”的问题,表面看似简单,实则涉及多个内核子系统与用户态组件的协同&…...
智慧医疗时代下的医疗设备智能控费系统解决方案
—以科技赋能医疗控费,构建精细化管理新生态 一、行业背景与现存痛点 (一)政策驱动与行业挑战 随着DRG/DIP支付改革全面落地、医保基金监管趋严,医疗机构面临“提质增效”与“成本管控”的双重压力。国家卫健委数据显示&#x…...
软件设计师2025
笔记链接 第5章:软件工程基础知识 第6章:结构化开发方法 第10章:网络和信息安全基础知识...
Umi+React+Xrender+Hsf项目开发总结
一、菜单路由配置 1.umirc.ts 中的路由配置 .umirc.ts 文件是 UmiJS 框架中的一个配置文件,用于配置应用的全局设置,包括但不限于路由、插件、样式等。 import { defineConfig } from umi; import config from ./def/config;export default defineCon…...
【软件设计师:数据结构】1.数据结构基础(一)
一 线性表 1.线性表定义 线性表是n个元素的有限序列,通常记为(a1,a2,…,an)。 特点: 存在惟一的表头和表尾。除了表头外,表中的每一个元素均只有惟一的直接前驱。除了表尾外,表中的每一个元素均只有惟一的直接后继。2.线性表的存储结构 (1)顺序存储 是用一组地址连续…...
linux_进程地址空间(虚拟地址空间)
一、进程地址空间是什么? 先看这样一个具体的例子 #include<stdlib.h> #include <stdio.h> #include<unistd.h> int main() {int a1;pid_t idfork();while(1){if(id0){printf("i am child,pid:%d,ppid:%d,a:%d ,&a:%p\n",getpid(…...
计操第四章存储管理
地址再定位...
尚硅谷-硅谷甄选项目记录
一、Vue3 1 基础配置 1.1 路径别名 vite.config.ts import { defineConfig } from vite import vue from vitejs/plugin-vue// 引入path,node提供的模块,可以获取文件或文件夹的路径 import path from pathexport default defineConfig({plugins: […...
c# LINQ-Query01
文章目录 查询数据源标准查询分两类即时查询已推迟流式处理非流式处理分类表聚合Aggregate<TSource,TAccumulate,TResult>(IEnumerable<TSource>, TAccumulate, Func<TAccumulate,TSource,TAccumulate>, Func<TAccumulate,TResult>)Aggregate<TSour…...
Vue3渲染引擎:虚拟DOM与响应式原理
Vue3渲染引擎:虚拟DOM与响应式原理 在当今的前端开发中,Vue.js作为一种流行的JavaScript框架,经常被用来构建用户界面。而Vue.js 3作为其最新版本,在性能和功能上进行了许多优化和改进。其中,Vue3渲染引擎的核心原理—…...
[dify]官方模板DeepResearch工作流学习笔记
一、功能 根据用户输入的主题进行多轮搜索并生成综合报告 1、流程分析 1.1 初始阶段 Start节点:接收用户输入的"depth"参数,决定搜索的深度/轮数 参数可以不填,不填的时候取默认值3 Create Array节点:根据depth参数…...
大模型系列(四)--- GPT2: Language Models are Unsupervised Multitask Learners
论文链接: Language Models are Unsupervised Multitask Learners 点评: GPT-2采用了与GPT-1类似的架构,将参数规模增加到了15亿,并使用大规模的网页数据集WebText 进行训练。正如GPT-2 的论文所述,它旨在通过无监督语…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(15):何と どういう
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(15):何と &どういう 1、前言(1)情况说明(2)工程师的信仰 2、知识点(1)かもしれません & ~…...
基于英特尔 RealSense D455 结构光相机实现裂缝尺寸以及深度测量
目录 一,相机参数规格 二,结合YOLO实例分割实现裂缝尺寸以及深度测量 2.1 应用场景 2.2 实现流程 2.3 效果展示 2.4 精度验证 2.5 实物裂缝尺寸以及深度测量效果展示 一,相机参数规格 英特尔 RealSense D455 是英特尔 RealSense D400 系…...
利用并行处理提高LabVIEW程序执行速度
在 LabVIEW 编程中,提升程序执行速度是优化系统性能的关键,而并行处理技术则是实现这一目标的有力武器。通过合理运用并行处理,不仅能加快程序运行,还能增强系统的稳定性和响应能力。下面将结合实际案例,深入探讨如何利…...
C++并发编程完全指南:从基础到实践
在当今多核处理器普及的时代,充分利用硬件并发能力已成为高性能编程的关键。C11引入的现代并发编程支持使得开发者能够以标准化、可移植的方式编写多线程程序。本文将全面介绍C并发编程的各个方面,从基础概念到实际应用,帮助您掌握这一重要技…...
vue3 element-plus 输入框回车跳转页面问题处理
问题描述: 当页面搜索条件只有一个的情况下,输入框不管有没有值,回车后会跳转页面 解决办法,给表单添加 submit.prevent <el-form ref"ruleForm" :model"search" label-width"120px" class&qu…...
从0开始学习大模型--Day03--Agent规划与记忆
规划(planning) 规划,可以为理解观察和思考。如果用人类来类比,当我们接到一个任务,我们的思维模式可能会像下面这样: 1、首先会思考怎么完成这个任务。 2、然后会审视手头上所拥有的工具,以及如何使用这…...
DevExpressWinForms-AlertControl-使用教程
文章目录 AlertControl-使用教程一、将 AlertControl 添加到 Form二、编辑 AlertControl 的 HtmlTemplateHTML Template Editor介绍编辑HTML Template 三、使用AlertControl弹出AlertAlert中的按钮事件获取 Alert 标题等信息向Alert传递参数 总结源码 AlertControl-使用教程 一…...
配电站室智能巡检:机器人 VS 固定摄像头,谁更胜一筹?
在配电站室巡检领域,传统人工巡检正逐渐被智能化手段取代。其中,机器人巡检与固定摄像头巡检成为两大热门选择。那么,它们究竟谁更胜一筹? 一、机器人巡检与固定摄像头巡检的对比 目前人工巡检工作主要以查看表计,设…...
脑图谱:脑机接口的必由之路——技术突破与产业转化的系统性思考
一、三维发育小鼠大脑图谱框架(DevCCF) 1. 技术原理与核心创新 DevCCF框架由宾夕法尼亚州立大学团队主导开发,其技术突破体现在多模态数据融合与跨尺度分析能力的革新: 多模态成像整合:采用高分辨率MRI(空间分辨率50-100μm)捕捉全脑宏观结构动态变化,结合光片荧光显…...
【网络编程】二、UDP网络套接字编程详解
文章目录 前言Ⅰ. UDP服务端一、服务器创建流程二、创建套接字 -- socketsocket 属于什么类型的接口❓❓❓socket 是被谁调用的❓❓❓socket 底层做了什么❓❓❓和其函数返回值有没有什么关系❓❓❓三、绑定对应端口号、IP地址到套接字 -- bind四、数据的发送和接收 -- `sendto…...
缓存替换算法与存储器管理的分页、分段、段页式管理联系
缓存替换算法与存储器管理的分页、分段、段页式管理在目标和机制上存在相似性,均涉及高效资源分配和地址映射,但应用层级和具体场景不同。以下是它们的联系与区别分析: 1. 核心联系:资源管理的共性 替换策略的必要性 无论是缓存&a…...
AI大模型基础设施:NVIDIA GPU和AMD MI300系列的区别
本文将从架构设计、性能、内存、功耗、软件生态、价格与性价比、供应链与市场表现等多个维度对比英伟达的GPU(以H100为代表)和AMD的Instinct MI300系列处理器(以MI300X GPU和MI300A APU为主)。以下是详细分析: 1. 架构…...
基于Matlab实现耦合模理论仿真程序
耦合模理论(Coupled Mode Theory,简称CMT)是一种广泛应用于光子学、微波工程和电子学领域的理论框架,用于分析和理解多模系统的相互作用。 耦合模理论主要研究两个或多个模式之间的能量交换,这些模式可以是电磁波、声…...
图片文件转base64存储在数据库
以下是将文件转换为Base64编码字符串的Java代码: import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Base64;public class ImageToBase64 {/*** 将图片文件转换为Base64字符串* param filePath 图片文件路径* r…...
我的世界云端服务器具体是指什么?
我的世界云端服务器是指一种基于互联网的多人游戏服务器,将游戏服务器运行在云平台上,而不是在本地计算机中,这使用户不需要考虑自身电脑的性能和网络稳定性,只需要通过网络连接到云端服务器,就可以享受到顺畅的游戏体…...
shell脚本实现远程重启多个服务器
直接deepseek帮写脚本 remoteReboot.sh #!/bin/bash # 配置文件路径(格式:每行一个服务器地址) SERVER_FILE"servers.list" # 读取服务器列表 mapfile -t SERVERS < "$SERVER_FILE" for server in "${SERVER…...
怎样快速变换 json 串里的多层集合
有一个 2 层的 json 串,下层是多个动态的 key-value,不含集合 / 数组类型。 {"Games": {"key1": "value1", "key2": value2,"key3":value3}} 现在要把下层变换成多层的集合。 {"Games":…...
FreeCAD傻瓜教程-涡轮蜗杆的快速绘制FCGear工作台的使用方法
起因:涡轮蜗轴的组合,是一种比较简单且高效的传动结构。可以实现减速、加速、转动角度的放大、缩小等应用。 如何绘制呢?我搜索了不少教程,看起来都挺复杂的,对于小白来说有点像天书。这里介绍和记录一下利用FreeCAD 的…...
【论文阅读】HunyuanVideo: A Systematic Framework For Large Video Generative Models
HunyuanVideo: A Systematic Framework For Large Video Generative Models 原文摘要 研究背景与问题 视频生成的变革性影响:近期视频生成技术的进步深刻改变了个人生活与行业应用。 闭源模型的垄断:主流视频生成模型(如Runway Gen-3、Luma …...
Search After+PIT 解决ES深度分页问题
1.深分页和search after 原理 深分页 (from/size)search_after数据定位全局排序后跳过前 N 条基于上一页最后一条的排序值定位排序开销每次请求重新全局排序 (O(N))仅首次全局排序,后续游标跳转 (O(1))内存消耗堆内存存储完整结果集 (高风险OOM)无堆内存累积 (安全…...
c语法高阶—(联合体,枚举,位域,编译器,宏定义,条件编译,条件编译,头文件)
目录 一 联合体(重要) 特性 总结 二 枚举(重要) 特性 总结: 三 位域(了解) 定义 特性 使用场景 优缺点分析表 位域的特点和使用方法 总结: 四 编译器(linux…...
SQL Server To Paimon Demo by Flink standalone cluster mode
需求:使用 Flink CDC 测试 SQL Server 连接 Paimon 操作:启动 Flink standalone cluster 后,接着启动 Flink SQL Client,则通过 Flink SQL Client 提交 insert & select job 到该 8081 cluster Flink SQL Client 执行案例 -…...
常用设计模式在 Spring Boot 项目中的实战案例
引言 在当今的软件开发领域,Spring Boot 以其高效、便捷的特性成为构建 Java 应用程序的热门框架。而设计模式作为软件开发中的宝贵经验总结,能够显著提升代码的可维护性、可扩展性和可复用性。本文将深入探讨几种常用设计模式在 Spring Boot 项目中的…...
4、反应釜压力监控系统 - /自动化与控制组件/reaction-vessel-monitor
76个工业组件库示例汇总 反应釜压力监控组件 这是一个用于反应釜压力监控的自定义组件,专为化工厂反应釜压力监控设计。采用苹果工业风格界面,简洁优雅,功能实用,易于使用。 功能特点 实时压力可视化:直观展示反应…...