📌人工智能: 「AI大模型」AI数据分析助手保姆级文档
📋 目录
- 一、工具类功能
- 二、所需环境
- 三、方法与调用示例(按需调用)
- 四、工具类源码(可直接复制)
一、工具类功能
加锁走SET key token NX PX,释放与续期用「先比对 token 再动作」的 Lua 脚本,用于跨进程抢同一份资源的互斥,依赖 Spring Data Redis,锁不可重入。
二、所需环境
JDK 17或以上 + Spring Boot 3.x或以上
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency>三、方法与调用示例(按需调用)
🔢方法序号:1
🎯方法用途:
- 注入 Spring Data Redis 的模板,建出一个可用的分布式锁组件
- 本类有状态,建成单例 Bean 复用,不要在每次抢锁时 new 一个
🧩方法定义:public RedisLockUtils(RedisTemplate<String, String> redisTemplate)
🗣️入参解释:public RedisLockUtils(Redis 模板)
📤返回值解释:RedisLockUtils,绑定在该模板上的锁组件
💡边界口径:
- 传
null当场抛IllegalArgumentException: redisTemplate 不能为 null,不留到第一次抢锁才炸 - 推荐注入
StringRedisTemplate,锁值本身是随机 token 字符串 - 实例本身线程安全,多个业务共用一个 Bean 即可
- 加锁走
SET key token NX PX lease,解锁与续期走比对 token 的 Lua 脚本
🧪方法示例:
new RedisLockUtils(stringRedisTemplate)装配完成后打日志,Redis 地址那一行拿到的是连上的实例new RedisLockUtils(null)抛IllegalArgumentException: redisTemplate 不能为 null
🔢方法序号:2
🎯方法用途:
- 不阻塞地抢一次锁,抢到返回凭证
Optional<String>,没抢到返回空 - 防重复提交、定时任务多实例只跑一个这类「抢不到就放弃」的场景用它
🧩方法定义:public Optional<String> tryLock(String key, Duration lease)
🗣️入参解释:public Optional<String> tryLock(锁键, 持锁时长)
📤返回值解释:Optional<String>,抢到锁时是本次凭证,抢不到时为Optional.empty()
💡边界口径:
- 凭证是随机 token,必须留着传给
unlock与renew - 锁已被别人持有返回空;Redis 超时或
setIfAbsent返回null也按「没抢到」处理,不抛异常 - 不可重入:同一线程再抢同一个 key 也是空
key为null或空白、lease不足 1 毫秒都抛IllegalArgumentException
🧪方法示例:
tryLock("order:settle:2026-10", Duration.ofSeconds(30))第一次抢拿到true- 同一个 key 再抢一次(锁还在自己手上)拿到
false,说明不可重入 tryLock(" ", Duration.ofSeconds(1))抛IllegalArgumentException,消息是「锁键 key 不能为null或空白」
🔢方法序号:3
🎯方法用途:
- 带等待的抢锁:在
maxWait内按带随机抖动的自旋重试,等到就用,等不到就放弃 - 任务必须执行、只是要排队抢锁的场景用它,而不是自己写
while + sleep
🧩方法定义:public Optional<String> tryLock(String key, Duration lease, Duration maxWait, Duration spinMillis)
🗣️入参解释:public Optional<String> tryLock(锁键, 持锁时长, 最长等待, 重试基准间隔)
📤返回值解释:Optional<String>,等到锁时是凭证,超时或被中断为空
💡边界口径:
- 重试间隔带随机抖动,避免多个等待者同一时刻一起打 Redis
maxWait允许 0,表示只试一次不排队- 等待期间线程被中断时,中断标记保持置位并返回空,不吞中断
lease与spinMillis必须为正且按毫秒精度生效
🧪方法示例:
- 持有者 400 毫秒后放手,等待方调
tryLock(key, lease, maxWait, spinMillis)拿到true,用时 417 毫秒 - 持有者随后的释放拿到
true,说明两边交接没有互相踩凭证 tryLock(key, lease, maxWait, Duration.ofMillis(0))抛IllegalArgumentException,因为重试间隔必须大于 0
🔢方法序号:4
🎯方法用途:
- 用加锁时拿到的凭证释放锁,凭证对得上才删键
- 挡住「A 的锁过期后 A 回来把 B 的锁删掉」这类误删,互斥才真的成立
🧩方法定义:public boolean unlock(String key, String token)
🗣️入参解释:public boolean unlock(锁键, 加锁时返回的凭证)
📤返回值解释:boolean,删掉了自己这把锁为true
💡边界口径:
- 比对与删除在同一段 Lua 里原子完成,不是「先 get 再 del」
- 锁已过期、已被别人持有、凭证不匹配、凭证为
null或空白,一律返回false且不抛异常 false不一定代表出错,常见含义是「这把锁早就不归你了」,业务据此决定补偿
🧪方法示例:
- 抢到锁后
unlock(key, token)用第一次的凭证释放拿到true - 紧接着再释放一次,拿到
false,已经无锁可解 - 拿着别人的锁键配一个错凭证去解,拿到
false unlock(key, null)与unlock(key, "")都拿到false,不抛异常
🔢方法序号:5
🎯方法用途:
- 用凭证把锁的过期时间重置为新的
lease,让长任务不至于跑到一半丢锁 - 业务耗时不确定时,按 lease 的三分之一起个定时任务持续续期
🧩方法定义:public boolean renew(String key, String token, Duration lease)
🗣️入参解释:public boolean renew(锁键, 凭证, 新的持锁时长)
📤返回值解释:boolean,续期成功为true
💡边界口径:
- 只有凭证与锁上的 token 一致才续,比对与
PEXPIRE走 Lua 原子完成 - 返回
false说明锁已经不是自己的,此时必须停手,不能继续跑临界区 lease同样必须为正、按毫秒精度生效- 续期只重置过期时间,不会改变持有者
🧪方法示例:
- 持有者
renew(key, token, Duration.ofSeconds(30))拿到true,锁的剩余时间被重置 - 用错凭证续期拿到
false
🔢方法序号:6
🎯方法用途:
- 模板方法:抢到锁执行业务并返回结果,业务无论正常返回还是抛异常都会解锁
- 省掉手写 try/finally,也不会把锁漏在异常路径上
🧩方法定义:public <T> T executeWithLock(String key, Duration lease, Supplier<T> action)
🗣️入参解释:public <T> T executeWithLock(锁键, 持锁时长, 有返回值的业务)
📤返回值解释:T,业务自己的返回值
💡边界口径:
- 抢不到锁直接抛
IllegalStateException,消息带上 key,业务一次都不会执行 - 业务抛异常时锁照样释放,异常原样往外传
- 业务跑完发现自己已经丢锁(lease 到期被接管)时,用
System.Logger记一条 warning,只留痕不改写已成功的结果 action传null抛IllegalArgumentException: action 不能为 null
🧪方法示例:
executeWithLock(key, lease, () -> "第 1 次执行")拿到第 1 次执行- 模板返回后立刻查锁状态,已释放拿到
true - 锁被别人持着时调它抛
IllegalStateException,同时业务执行次数拿到0 - 业务自己抛异常后,紧接着再抢一次同一把锁拿到
true,说明 finally 里已解锁
🔢方法序号:7
🎯方法用途:
- 无返回值版的模板方法,适合只是「跑一段互斥逻辑」而不需要结果的场景
- 与有返回值版同一套加解锁流程,避免两个版本行为漂移
🧩方法定义:public void executeWithLock(String key, Duration lease, Runnable action)
🗣️入参解释:public void executeWithLock(锁键, 持锁时长, 无返回值的业务)
📤返回值解释:void,业务自己通过副作用交付结果
💡边界口径:
- 内部转调方法6 的
Supplier版,异常与释放口径完全一致 - 抢不到锁同样抛
IllegalStateException action传null抛IllegalArgumentException
🧪方法示例:
executeWithLock(key, lease, () -> counter.incrementAndGet())跑完后业务被执行次数拿到1executeWithLock(key, lease, (Runnable) null)抛IllegalArgumentException: action 不能为 null
🔢方法序号:8
🎯方法用途:
- 带等待参数的模板方法:在
maxWait内排队抢锁,等到才执行业务 - 「一定要跑,但可以等」的任务用它,超时才抛异常
🧩方法定义:public <T> T executeWithLock(String key, Duration lease, Duration maxWait, Duration spinMillis, Supplier<T> action)
🗣️入参解释:public <T> T executeWithLock(锁键, 持锁时长, 最长等待, 重试基准间隔, 有返回值的业务)
📤返回值解释:T,业务自己的返回值
💡边界口径:
- 等待与抖动口径同方法3,等不到锁抛
IllegalStateException并带上 key - 业务执行期间同样受 lease 约束,长任务要配
renew - 解锁时机与业务异常处理同方法6
🧪方法示例:
- 原持有者放手拿到
true - 本调用在
maxWait内等到锁并执行,返回值拿到等到锁才跑的业务 - 等待超过
maxWait时抛IllegalStateException,业务一次都没跑
四、工具类源码(可直接复制)
📦本工具类源码:95-Redis分布式锁工具类
📦 需要「Java企业级工具类全家桶(1-100)」点点关注点点赞,回复「java工具类」可领取100个工具类的完整源码
💡 工具类已调试通过,复制粘贴即可使用,省时省力
💡 可保存到自己网盘,永久有效
觉得对您有帮助,麻烦点点关注啦,您的关注是我创作的最大动力~ 🎯