Redisson常用方法
Redisson
参考: 原文链接
定义:Redisson 是一个用于与 Redis 进行交互的 Java 客户端库
优点:很多
1. 入门
1.1 安装
<!--redission-->
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.31.0</version>
</dependency><!--starter-->
<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.18.0</version>
</dependency>
1.2 配置
@Configuration
public class RedissonConfig {@Beanpublic RedissonClient redissonClient(){// 配置Config config = new Config();config.useSingleServer().setAddress("redis://192.168.133.136:6379").setPassword("111111");// 创建RedissonClient对象return Redisson.create(config);}
}
---------------------------------使用yml配置-----------------------------------------
redisson:singleServerConfig:address: "redis://192.168.133.136:6379" # Redis 服务器地址password: "111111" # 如果有密码,填入密码connectionMinimumIdleSize: 10 # 最小空闲连接数connectionPoolSize: 64 # 连接池大小idleConnectionTimeout: 10000 # 空闲连接最大存活时间connectTimeout: 10000 # 连接超时timeout: 10000 # 请求超时retryAttempts: 3 # 重试次数retryInterval: 1500 # 重试间隔(毫秒)
1.3 使用
@Autowired
private RedissonClient redissonClient;@Test
void testRedisson() throws Exception {//获取锁(可重入),指定锁的名称RLock lock = redissonClient.getLock("sanjin");//尝试获取锁,参数分别是:获取锁的最大等待时间(期间会重试),锁自动释放时间,时间单位boolean isLock = lock.tryLock(1, 10, TimeUnit.SECONDS);//判断获取锁成功if (isLock) {try {System.out.println("执行业务");} finally {//释放锁lock.unlock();}}
}
----------------结果------------------
执行业务
2. 可重入锁原理
2.1 加锁
这是可重入锁接口,
public interface RLock extends Lock, RLockAsync {String getName();void lockInterruptibly(long var1, TimeUnit var3) throws InterruptedException;// 有等待时间boolean tryLock(long var1, long var3, TimeUnit var5) throws InterruptedException;// 无等待时间void lock(long var1, TimeUnit var3);boolean forceUnlock();boolean isLocked();boolean isHeldByThread(long var1);boolean isHeldByCurrentThread();int getHoldCount();long remainTimeToLive();
}
看一下lock实现方法, 明白大体逻辑即可
- 如果成功,立即返回,如果失败,订阅锁的释放事件
- 在锁释放时,重新尝试获取锁,如果仍未成功(又被抢了),根据 TTL 再次等待,直到获取锁成功
- 在方法退出前,取消对锁释放事件的订阅,避免资源浪费
private void lock(long leaseTime, TimeUnit unit, boolean interruptibly) throws InterruptedException {// 保证只有锁的持有线程可以释放锁long threadId = Thread.currentThread().getId();// -1通常表示锁的等待时间设置为无限制(立即尝试获取锁)// 如果返回 null,表示成功获取到锁, ttl表示锁的剩余过期时间Long ttl = this.tryAcquire(-1L, leaseTime, unit, threadId);if (ttl != null) {// 如果未获取到锁,订阅锁的释放事件CompletableFuture<RedissonLockEntry> future = this.subscribe(threadId);// 设置订阅超时,防止由于网络或其他问题导致的长时间等待this.pubSub.timeout(future);RedissonLockEntry entry;// 阻塞等待订阅结果if (interruptibly) {entry = (RedissonLockEntry)this.commandExecutor.getInterrupted(future);} else {entry = (RedissonLockEntry)this.commandExecutor.get(future);}try {// 进入一个无限循环,不断尝试重新获取锁,直到成功为止while(true) {// 再次尝试获取锁ttl = this.tryAcquire(-1L, leaseTime, unit, threadId);// 如果返回 null,表示成功获取锁,直接退出方法if (ttl == null) {return;}// 如果返回一个非 null 的值 ttl,表示锁仍被占用,需要根据剩余时间等待if (ttl >= 0L) {try {// 使用计数器(CountDownLatch 的一种实现)来等待锁的释放通知entry.getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);} catch (InterruptedException var14) {if (interruptibly) {throw var14;}entry.getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);}// 如果 TTL 为负数(可能表示锁的持有者未设置自动过期时间),线程将等待一个释放通知} else if (interruptibly) {entry.getLatch().acquire();} else {entry.getLatch().acquireUninterruptibly();}}} finally {// 无论锁是否成功获取,最终都会释放订阅,以避免资源泄漏this.unsubscribe(entry, threadId);}}
}
具体加锁逻辑tryAcquire
KEYS[1]
:锁的 Redis 键,通常为锁的唯一标识ARGV[1]
:锁的过期时间(毫秒)ARGV[2]
:当前线程的唯一标识(value)
<T> RFuture<T> tryLockInnerAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) {// 异步执行 Redis 的 EVAL 命令return this.evalWriteAsync(this.getRawName(), LongCodec.INSTANCE, command,// 判断锁是否已存在,如果锁不存在,创建锁并设置过期时间"if (redis.call('exists', KEYS[1]) == 0) then " +// 使用 HINCRBY 创建锁并设置当前线程的持有次数为 1,利用hash结构"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +// 设置锁的过期时间,确保锁在持有者崩溃后释放"redis.call('pexpire', KEYS[1], ARGV[1]); " +// 返回 nil 表示锁已成功获取"return nil; " +"end; " +// 锁已被当前线程持有的情况, 判断锁是否被当前线程持有"if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +// 增加持有次数(支持可重入)"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +// 更新锁的过期时间"redis.call('pexpire', KEYS[1], ARGV[1]); " +"return nil; " +"end; " +// 返回锁的剩余过期时间(毫秒),用于通知调用者等待或重试"return redis.call('pttl', KEYS[1]);",Collections.singletonList(this.getRawName()), new Object[]{unit.toMillis(leaseTime), this.getLockName(threadId)});}
具体加锁逻辑如下图
2.2 续锁
主要就是根据leaseTime判断如何操作
指定了leaseTime:设置过期时间为leaseTime,不启用看门狗
不指定leaseTime:设置默认过期时间(30s),并且启用看门狗
指不指定是看 lock.lock() 是否传入了值
private <T> RFuture<Long> tryAcquireAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId) {RFuture ttlRemainingFuture;// 尝试获取锁if (leaseTime > 0L) {// 使用指定的过期时间尝试获取锁, 适合短期锁场景,过期后无需续期ttlRemainingFuture = this.tryLockInnerAsync(waitTime, leaseTime, unit, threadId, RedisCommands.EVAL_LONG);} else {// 使用内部默认的锁租约时间 internalLockLeaseTime(30秒), 适合长期锁场景,通常需要续期机制ttlRemainingFuture = this.tryLockInnerAsync(waitTime, this.internalLockLeaseTime, TimeUnit.MILLISECONDS, threadId, RedisCommands.EVAL_LONG);}// 处理锁获取结果CompletionStage<Long> f = ttlRemainingFuture.thenApply((ttlRemaining) -> {// 如果 ttlRemaining == null,说明锁成功获取if (ttlRemaining == null) {if (leaseTime > 0L) {// 将 internalLockLeaseTime 更新为指定的租约时间,后续 Redis 锁命令会使用该值设置锁的过期时间this.internalLockLeaseTime = unit.toMillis(leaseTime);} else {// 看门狗机制续租// 调用 scheduleExpirationRenewal 方法,开启后台续期任务,确保锁不会因过期时间耗尽而释放this.scheduleExpirationRenewal(threadId);}}// 表示锁已被其他线程持有,返回锁的剩余有效时间return ttlRemaining;});return new CompletableFutureWrapper(f);
}
2.3 解锁
最外层的解锁方法
public void unlock() {try {// 异步调用解锁方法,并等待其执行完成this.get(this.unlockAsync(Thread.currentThread().getId()));} catch (RedisException var2) {if (var2.getCause() instanceof IllegalMonitorStateException) {throw (IllegalMonitorStateException)var2.getCause();} else {throw var2;}}
}
解锁并处理解锁后的步骤(取消看门狗机制…)
public RFuture<Void> unlockAsync(long threadId) {// 异步调用解锁方法RFuture<Boolean> future = this.unlockInnerAsync(threadId);// 使用 handle() 方法处理解锁结果和异常CompletionStage<Void> f = future.handle((opStatus, e) -> {// 取消锁的续期this.cancelExpirationRenewal(threadId);// 如果异步操作抛出异常,包装并抛出 CompletionExceptionif (e != null) {throw new CompletionException(e);} else if (opStatus == null) {// 如果解锁操作状态为 null,说明当前线程未持有锁,抛出 IllegalMonitorStateExceptionIllegalMonitorStateException cause = new IllegalMonitorStateException("attempt to unlock lock, not locked by current thread by node id: " + this.id + " thread-id: " + threadId);throw new CompletionException(cause);} else {// 如果操作成功,则返回 nullreturn null;}});return new CompletableFutureWrapper(f);
}
具体解锁的redis执行步骤
参数:
KEYS[1]
:锁的键名。KEYS[2]
:用于发布解锁事件的频道名。ARGV[1]
:解锁事件消息。ARGV[2]
:锁的过期时间。ARGV[3]
:锁的名称(用于计数器)。
步骤:
-
检查当前线程是否持有锁
-
减少锁计数器
-
如果计数器值大于零,更新锁的过期时间
-
如果计数器值为零,删除锁并发布解锁事件
protected RFuture<Boolean> unlockInnerAsync(long threadId) {return this.evalWriteAsync(this.getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,// 检查指定的锁是否存在。如果不存在(0),返回 nil,表示当前线程没有持有锁。"if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then " +"return nil;" +"end;" +// 将锁的计数器减一。如果当前线程持有锁,这个操作会减少锁的计数器值"local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1);" +// 如果锁计数器值仍大于零,说明有其他线程持有锁,需要更新锁的过期时间"if (counter > 0) then " +// 更新锁的过期时间"redis.call('pexpire', KEYS[1], ARGV[2]); " +// 表示解锁操作成功但锁仍被其他线程持有"return 0; " +"else " +// 如果计数器值为零,说明当前线程是最后一个持有锁的线程// 删除锁"redis.call('del', KEYS[1]); " +// 发布解锁事件通知其他等待的线程"redis.call('publish', KEYS[2], ARGV[1]); " +// 表示解锁成功且锁已被完全释放"return 1; " +"end; " +// 如果条件不满足,返回 nil"return nil;",Arrays.asList(this.getRawName(), this.getChannelName()),new Object[]{LockPubSub.UNLOCK_MESSAGE, this.internalLockLeaseTime, this.getLockName(threadId)});
}
图解:
3. 其他锁
3.1 红锁和多锁的区别
RedLock 是一种更为复杂的分布式锁实现,保证了分布式环境中的高可用性和容错性,但需要多个 Redis 实例进行协调
多锁 的实现简单,但可靠性差,容易受到单点故障的影响,不适合对安全性和可靠性要求较高的应用
特点 | RedLock | 多锁(Multiple Locks) |
---|---|---|
实现方式 | 使用多个独立的 Redis 实例,保证多数节点成功 | 每个 Redis 实例独立设置锁 |
容错性 | 高,支持在大多数节点上获取锁 | 低,不能保证一致性和容错性 |
锁的获取 | 需要在大多数实例中成功获取 | 在任意一个实例上获取锁即可 |
安全性 | 提供了更高的安全性和可靠性 | 相对简单,但不适用于复杂场景 |
网络分区容忍性 | 可以容忍部分节点失败,但不是所有 | 不适合面对网络分区或节点故障的场景 |
3.2 简单演示
public static void main(String[] args) {String lockKey = "myLock";Config config = new Config();config.useSingleServer().setPassword("123456").setAddress("redis://127.0.0.1:6379");Config config2 = new Config();config.useSingleServer().setPassword("123456").setAddress("redis://127.0.0.1:6380");Config config3 = new Config();config.useSingleServer().setPassword("123456").setAddress("redis://127.0.0.1:6381");RLock lock = Redisson.create(config).getLock(lockKey);RLock lock2 = Redisson.create(config2).getLock(lockKey);RLock lock3 = Redisson.create(config3).getLock(lockKey);RedissonRedLock redLock = new RedissonRedLock(lock, lock2, lock3);try {redLock.lock();} finally {redLock.unlock();}
}
3.3 CAP之间的取舍
CAP 原则又称 CAP 定理, 指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性), 三者不可得兼
一致性© : 在分布式系统中的所有数据备份, 在同一时刻是否同样的值(等同于所有节点访问同一份最新的数据副本)
可用性(A): 在集群中一部分节点故障后, 集群整体是否还能响应客户端的读写请求(对数据更新具备高可用性)
分区容忍性§: 以实际效果而言, 分区相当于对通信的时限要求. 系统如果不能在时限内达成数据一致性, 就意味着发生了分区的情况, 必须就当前操作在 C 和 A 之间做出选择
4. Redisson的限流功能
常见的限流功能:固定窗口算法、滑动窗口算法、漏桶算法、令牌桶算法
利用Redisson的令牌桶限流
@Test
void testLimiter() {// 创建一个限流器RRateLimiter rateLimiter = redissonClient.getRateLimiter("sanjin");// 初始化最大流速为每秒10个令牌rateLimiter.trySetRate(RateType.OVERALL, 10, 1, RateIntervalUnit.SECONDS);for (int i = 0; i < 20; i++) {// 尝试获取一个令牌boolean b = rateLimiter.tryAcquire();if (b) {System.out.println("成功获取第"+ i +"个令牌");} else {System.out.println("被第" + i + "次限流了");}}
}
---------------------------结果-----------------------------------
成功获取第0个令牌
成功获取第1个令牌
成功获取第2个令牌
成功获取第3个令牌
成功获取第4个令牌
成功获取第5个令牌
成功获取第6个令牌
成功获取第7个令牌
成功获取第8个令牌
成功获取第9个令牌
被第10次限流了
被第11次限流了
被第12次限流了
被第13次限流了
被第14次限流了
被第15次限流了
被第16次限流了
被第17次限流了
被第18次限流了
被第19次限流了
相关文章:
Redisson常用方法
Redisson 参考: 原文链接 定义:Redisson 是一个用于与 Redis 进行交互的 Java 客户端库 优点:很多 1. 入门 1.1 安装 <!--redission--> <dependency><groupId>org.redisson</groupId><artifactId>redisson</artifa…...
【树莓派4B】MindSpore lite 部署demo
一个demo,mindspore lite 部署在树莓派4B ubuntu22.04中,为后续操作开个门! 环境 开发环境:wsl-ubuntu22.04分发版部署环境:树莓派4B,操作系统为ubuntu22.04mindspore lite版本:mindspore-li…...
ESP32-S3模组上跑通ES8388(30)
接前一篇文章:ESP32-S3模组上跑通ES8388(29) 二、利用ESP-ADF操作ES8388 2. 详细解析 上一回终于解析完了es8388_init函数的所有代码。本回回到调用它的地方,继续往下讲解。 我们是从ESP32-S3模组上跑通ES8388(7)-CSDN博客开始进入es8388_init函数,展开对于它的解析的…...
网络安全渗透测试概论
渗透测试,也称为渗透攻击测试是一种通过模拟恶意攻击者的手段来评估计算机系统、网络或应用程序安全性的方法。 目的 旨在主动发现系统中可能存在的安全漏洞、脆弱点以及潜在风险,以便在被真正的恶意攻击者利用之前,及时进行修复和加固&…...
.NET6 WebAPI从基础到进阶--朝夕教育
1、环境准备 1. Visual Studio 2022 2. .NET6 平台支持 3. Internet Information Services 服务器( IIS ) 4. Linux 服务器 【 CentOS 系统】 ( 跨平台部署使用 ) 5. Linux 服务器下的 Docker 容器( Docker 部署使用) …...
opencv通过3种算子进行边缘提取
Scharr算子是效果比较好的,但从肉眼看sobel算子比较顺眼 # 导入OpenCV库,用于图像处理 import cv2 import numpy as np # 从matplotlib库中导入pyplot模块,用于绘制图像 from matplotlib import pyplot as plt # 创建一个名为window的窗口,窗…...
【KodExplorer】可道云KodExplorer-个人网盘安装使用
说明:安装kodExplorer (不是Kodbox);Kodbox需求服务器至少2核4G内存,要求环境具备php/redis/mysql/。安装kodExplorer 就是比较方便简单部署,个人版免费。 一、安装环境需求 服务器: Windows,…...
并查集基础
abstract 并查集(Union-Find Set)是一种数据结构,主要用于处理动态连通性问题(Dynamic Connectivity Problem),例如在图论中判断两点是否属于同一个连通分量,以及动态地合并集合。 它广泛应用…...
FPGA 16 ,Verilog中的位宽:深入理解与应用
目录 前言 一. 位宽的基本概念 二. 位宽的定义方法 1. 使用向量变量定义位宽 ① 向量类型及位宽指定 ② 位宽范围及位索引含义 ③ 存储数据与字节数据 2. 使用常量参数定义位宽 3. 使用宏定义位宽 4. 使用[:][-:]操作符定义位宽 1. 详细解释 : 操作符 -: 操作符 …...
day2 数据结构 结构体的应用
思维导图 小练习: 定义一个数组,用来存放从终端输入的5个学生的信息【学生的信息包含学生的姓名、年纪、性别、成绩】 1>封装函数 录入5个学生信息 2>封装函数 显示学生信息 3>封装函数 删除第几个学生信息,删除后调用显示学…...
原创 传奇996_55——后端如何点击npc隐藏主界面
点击图片退出,举例: |linkexit Img|ax0.5|ay0.5|percentx50|percenty50|imgpublic/touming2.png|hideMain1|linkexit <Img|x0|y0|esc1|show4|bg1|move0|imgcustom/new/longhun/bg.png|loadDelay0|reset1|hideMain1>...
java+springboot+mysql法律咨询网
项目介绍: 使用javaspringbootmysql开发的法律咨询网(文书),系统包含管理员、用户角色,功能如下: 管理员:登录系统;用户管理;文章管理(法律知识)…...
【AIGC】如何高效使用ChatGPT挖掘AI最大潜能?26个Prompt提问秘诀帮你提升300%效率的!
还记得第一次使用ChatGPT时,那种既兴奋又困惑的心情吗?我是从一个对AI一知半解的普通用户,逐步成长为现在的“ChatGPT大神”。这一过程并非一蹴而就,而是通过不断的探索和实践,掌握了一系列高效使用的技巧。今天&#…...
HarmonyOS-高级(四)
文章目录 应用开发安全应用DFX能力介绍HiLog使用指导HiAppEvent 🏡作者主页:点击! 🤖HarmonyOS专栏:点击! ⏰️创作时间:2024年12月11日11点18分 应用开发安全 应用隐私保护 隐私声明弹窗的作…...
国科大智能设备安全-APK逆向分析实验
APK逆向分析实验 使用APK常用逆向分析工具,对提供的移动应用程序APK文件进行逆向分析,提交逆向后代码和分析报告。具体任务如下: 任务一:安装并熟悉Apktool、Jadx等APK常用逆向工具的使用方法,对提供的Facebook Updat…...
Batch Normalization和 Layer Normalization
Batch Normalization和 Layer Normalization Batch Normalization (BN) 和 Layer Normalization (LN) 是深度学习中常用的归一化技术,它们的主要目的是加速训练、提高模型的收敛速度和稳定性。以下是对这两种归一化技术的详细讲解: 1. Batch Normalizat…...
数据结构——顺序表
顺序表的简单介绍 顺序表的概念:顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。 特点:顺序表的特点是可以通过元素的索引快速访问数据,其访问时间复杂度…...
C语言中互斥锁、信号量和条件变量的所有相关函数、参数、返回值和说明
1. 互斥锁(Mutex)的使用 互斥锁用于保护共享数据,防止多个线程同时修改它。 #include <pthread.h> #include <stdio.h> #include <stdlib.h> // 定义一个全局共享变量 int shared_counter 0; // 定义一个互斥锁 pthrea…...
(前序 简单)leetcode 226翻转二叉树
代码随想录说用前序遍历和后序遍历方便,而中序遍历比较绕。 活用自定义函数使程序结构更为清晰 这里用的是前序遍历,根结点root指向left和root,交换root的左右指向 执行过程: 也就是交换下例的 2 ,7 使得交换后&…...
搭建springmvc项目
什么是springmvc MVC它是一种设计理念。把程序按照指定的结构来划分: Model模型 View视图 Controller控制层 springmvc框架是spring框架的一个分支。它是按照mvc架构思想设计的一款框架。 springmvc的主要作用: 接收浏览器的请求数据,对数据进行处理,…...
解惑(一) ----- super(XXX, self).__init__()到底是代表什么含义
转载:self参数 - __ init__ ()方法 super(Net, self).__init__()是什么_super(net, self).init()-CSDN博客 相信大家在很多场合特别是写神经网络的代码的时候都看到过下面的这种代码: import torch import torch.nn as nn import torch.nn.functional …...
23种设计模式之责任链模式
目录 1. 简介2. 代码2.1 AbstractLogger(抽象处理者)2.2 InfoLogger (具体处理者)2.3 DebugLogger (具体处理者)2.4 ErrorLogger (具体处理者)2.5 Test (测试)…...
电感2222
1 电感 1电感是什么 2 电感的电流不能突变:电容是两端电压不能突变 3 电感只是限制电流变化速度...
车牌识别OCR授权:助力国产化升级,全面提升道路监控效率
政策背景:国产化升级,推动道路监控产业转型 随着国家对信息安全的重视,国内各大公安、政企机构已进入全面升级国产化平台的实施阶段。根据最新的政策要求,公安和政府部门必须在未来三年内完成平台的国产化替换工作。这一举措不仅…...
【人工智能-中级】卷积神经网络(CNN)的中阶应用:从图像分类到目标检测
文章目录 卷积神经网络(CNN)的中阶应用:从图像分类到目标检测1. 图像分类:CNN的基础应用CNN结构概述经典网络架构2. 目标检测:从分类到定位基于区域的目标检测方法单阶段目标检测方法边界框回归与NMS(Non-Maximum Suppression)3. 深度学习中的目标检测挑战与解决方案4. …...
从资产流动分析WIF市场潜力X.game深究其他未知因素
近日,两则关于WIF最新消息引起了投资者们的注意。据报道,11月28日Vintermute在过去13小时内累计从Binance交易所提取了价值533万美元的WIF,此举不仅彰显了其强大的资金实力,更在某种程度上推动了WIF币价的反弹;另一方面…...
【工具变量】上市公司企业经营困境指数数据(Zscore、Oscore、RLPM、Merton DD)2000-2021年
一、资料范围:包括Zscore、Oscore、RLPM、Merton DD,经营困境说明如下:(1)Zscore:以2.67和1.81作为临界值计算样本得分所处的范围。Zscore>2.67 为财务状况良好,发生破产的可能性较小。Zscor…...
freeswitch(监听、旁听)
亲测版本centos 7.9系统–》 freeswitch1.10.9 本人freeswitch安装路径(根据自己的路径进入) /usr/local/freeswitch/etc/freeswitch使用场景: 比如A和B在通话,C想监听他们通话内容,其他设备是不知道有人在监听的使用方法: 进入dialplan/default.xml 在配置表添加 <…...
php基础:命名空间
1.PHP 命名空间可以解决以下两类问题: 1.用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。 2.为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,以提高源代码的可读…...
SAP FICO物料分类账实操
物料分类账所涉及到的差异从采购入库的时候就可能已经产生,接下来从创建物料主数据开始对可能产生差异地方进行分析。其中有些操作步骤在标准价格估算这一篇博文中已经有过演示,可以先做了解。 其中的某些创建在有直接可用的情况下是非必须的࿰…...
【信息系统项目管理师】高分论文:论信息系统项目的整合管理(移动警务通系统)
更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 正文1、制定项目章程2、制定项目管理计划3、指导与管理项目工作4、管理项目知识5、监控项目工作6、实施整体变更控制7、结束项目或阶段正文 2022年2月,我有幸作为项目经理参加了“某市公安移动警务通系统”项…...
学习笔记069——Java集合框架
文章目录 集合1、List 接口2、Set 接口3、Map3.1、Map 常用实现类 集合 需要创建多个对象,但是数量和类型不确定。 集合是 Java 提供的一种类型,功能和数组类似,但是长度和数据类型都是动态。 集合框架(包括很多类和接口&#…...
JIS-CTF: VulnUpload靶场渗透
JIS-CTF: VulnUpload来自 <https://www.vulnhub.com/entry/jis-ctf-vulnupload,228/> 1,将两台虚拟机网络连接都改为NAT模式 2,攻击机上做namp局域网扫描发现靶机 nmap -sn 192.168.23.0/24 靶机IP地址192.168.23.162,攻击机IP地址192.168.23.140…...
2024年食堂采购系统源码技术趋势:如何开发智能的供应链管理APP
本篇文章,小编将与大家一同探讨2024年食堂采购系统的技术趋势,并提供开发更智能的供应链管理APP的策略。 一、2024年食堂采购系统的技术趋势 1.人工智能与机器学习的深度应用 在2024年,AI和机器学习在食堂采购系统中的应用将更加普遍。这些…...
Flink CDC实时同步mysql数据
官方参考资料: https://nightlies.apache.org/flink/flink-cdc-docs-master/zh/docs/connectors/flink-sources/mysql-cdc/ Apache Flink 的 Change Data Capture (CDC) 是一种用于捕获数据库变化(如插入、更新和删除操作)的技术。Flink CDC…...
解决MAC装win系统投屏失败问题(AMD显卡)
一、问题描述 电脑接上HDMI线后,电脑上能显示有外部显示器接入,但是外接显示器无投屏画面 二、已测试的方法 1 更改电脑分辨,结果无效 2 删除BootCamp,结果无效 3更新电脑系统,结果无效 4 在设备管理器中&#…...
【数据结构——查找】二叉排序树(头歌实践教学平台习题)【合集】
目录😋 任务描述 相关知识 测试说明 我的通关代码: 测试结果: 任务描述 本关任务:实现二叉排序树的基本算法。 相关知识 为了完成本关任务,你需要掌握:二叉树的创建、查找和删除算法。具体如下: (1)由…...
【NumPy进阶】:内存视图、性能优化与高级线性代数
目录 1. 深入理解 NumPy 的内存视图与拷贝1.1 内存视图(View)1.1.1 创建视图1.1.2 视图的特点 1.2 数组拷贝(Copy)1.2.1 创建拷贝1.2.2 拷贝的特点 1.3 视图与拷贝的选择 2. NumPy 的优化与性能提升技巧2.1 向量化操作示例&#x…...
[C++]多态
1. 什么是多态性? 1.定义 多态性是指同一个函数或操作在不同对象上表现出不同的行为。 2.分类 C 中的多态性主要分为两种: 1.编译时多态性(静态多态性): 编译时决定调用哪个函数。通过 函数重载 和 运算符重载 实…...
文本编辑器与正则表达式
1. VIM 编辑器 1.1 VIM 基本概念 VIM 是一个高度可定制的文本编辑器,广泛用于程序员的日常开发中。与传统的文本编辑器不同,VIM 基于模式操作,具有以下几个主要特点: 普通模式:用于浏览和修改文本。插入模式&#x…...
鲲鹏麒麟安装Kafka-v1.1.1
因项目需要在鲲鹏麒麟服务器上安装Kafka v1.1.1,因此这里将安装配置过程记录下来。 环境说明 # 查看系统相关详细信息 [roottest kafka_2.12-1.1.1]# uname -a Linux test.novalocal 4.19.148 #1 SMP Mon Oct 5 22:04:46 EDT 2020 aarch64 aarch64 aarch64 GNU/Li…...
scala基础_数据类型概览
Scala 数据类型 下表列出了 Scala 支持的数据类型: 类型类别数据类型描述Scala标准库中的实际类基本类型Byte8位有符号整数,数值范围为 -128 到 127scala.Byte基本类型Short16位有符号整数,数值范围为 -32768 到 32767scala.Short基本类型I…...
【重生之我要苦学C语言】文件操作
文件操作 为什么使用文件 如果没有文件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失了,等再次运行程序,是看不到上次程序的数据的,如果要将数据进行持久化的保…...
Python中PyTorch详解
文章目录 Python中PyTorch详解一、引言二、PyTorch核心概念1、张量(Tensor)1.1、创建张量1.2、张量操作 2、自动求导(Autograd)2.1、自动求导示例 三、构建神经网络1、使用nn模块2、优化器(Optimizer) 四、…...
Codigger SIDE之Helix编辑器
在Codigger的多维世界中,Helix编辑器以其卓越的性能和灵活性,成为开发者手中的利剑。基于Rust构建,Helix不仅继承了Vim编辑器的经典特性,更以其现代化的功能,重新定义了代码编辑的边界。 模式切换的艺术 Helix的模式切…...
vue3+echarts+websocket分时图与K线图实时推送
一、父组件代码: <template> <div class"chart-box" v-loading"loading"> <!-- tab导航栏 --> <div class"tab-box"> <div class"tab-list"> <div v-for"(item, index) in tabList…...
Maven常用插件清单
Maven 是一个强大的项目管理和构建工具,它使用插件来执行各种构建生命周期任务。以下是常用的一些 Maven 构建插件及其主要用途: 1. Maven Compiler Plugin 用途:编译Java源代码。配置示例:<build><plugins><plu…...
敏捷项目管理
虽然一直在践行敏捷开发,包括站会、尝试使用Confluence做知识wiki、每周分享等等,当然项目日常使用的coding、禅道、jira 项目管理和 jenkins 、git之类的CICD工具更不必说,但确实没有系统地去学习过敏捷开发管理。昨天被人问到敏捷开发到底是…...
牛客小白月赛107(A~E)
文章目录 A Cidoai的吃饭思路code B Cidoai的听歌思路code C Cidoai的植物思路code D Cidoai的猫猫思路code E Cidoai的可乐思路code 牛客小白月赛107 A Cidoai的吃饭 思路 签到题,按题意模拟即可 code void solve(){int n,a,b,c;cin >> n >> a &g…...
【传感器技术】第6章 压电式传感器,压电材料,压电效应,电压放大器
关注作者了解更多 我的其他CSDN专栏 过程控制系统 工程测试技术 虚拟仪器技术 可编程控制器 工业现场总线 数字图像处理 智能控制 传感器技术 嵌入式系统 复变函数与积分变换 单片机原理 线性代数 大学物理 热工与工程流体力学 数字信号处理 光电融合集成电路…...