1、先贴代码
@RequestMapping(value = "/update", method = RequestMethod.POST)
@ResponseBody
public Result update(@RequestBody Employee employee) {
// 修改数据库(存在线程不安全 需要使用redison设置分布式锁 防止被修改)
// 设置分布式锁
RLock lock = redissonClient.getLock("Lock:employ:"+employee.getId());
try {
if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {
try {
Employee employee1 = employeeService.getById(employee.getId());
if (employee1 == null) {
return Result.error("没有该员工");
}
boolean b = employeeService.updateById(employee);
if(b)
{
// 删除缓存
Boolean delete = redisTemplate.delete("employee" + employee.getId());
if(!delete){
return Result.error("缓存删除失败");
}
System.out.println("缓存删除成功");
return Result.success(employee,"员工信息修改成功");
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
// 关键:检查当前线程是否持有锁,避免误释放
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return Result.error("获取锁被中断");
}
return Result.error("获取锁失败");
}
2、说明中断
catch (InterruptedException e) {
Thread.currentThread().interrupt();
return Result.error("获取锁被中断");
}
为什么要写这个,因为中断异常会很常见
下面是AI生成的 简单来讲:
1、主动被中断 2、线程池提前关闭(这个常见点 比如线程池的shutdown和shutdownnow(强制关闭),线程被中断)3、用户操作(比如取消操作)
1. 线程被其他线程主动中断
当其他线程调用当前线程的
interrupt()
方法时,tryLock(10, 30, TimeUnit.SECONDS)
会立即抛出InterruptedException
。示例场景:
java
// 主线程 Thread updateThread = new Thread(() -> { employeeController.update(employee); // 调用更新接口 }); updateThread.start(); // 5秒后取消操作 Thread.sleep(5000); updateThread.interrupt(); // 中断更新线程,触发InterruptedException
可能的业务场景:
- 用户点击 "取消" 按钮,中断正在执行的更新操作。
- 系统资源紧张时,通过线程池的
shutdownNow()
中断所有正在执行的任务。2. 线程池关闭时中断任务
如果你使用线程池执行更新操作,调用
ExecutorService.shutdownNow()
会向所有线程发送中断信号。示例:
java
ExecutorService executor = Executors.newFixedThreadPool(10); Future<?> future = executor.submit(() -> { employeeController.update(employee); // 在线程池中执行更新 }); // 关闭线程池并中断未完成的任务 executor.shutdownNow(); // 触发所有线程的InterruptedException
3. 超时控制中的中断
虽然
tryLock(10, 30, TimeUnit.SECONDS)
的超时是由 Redisson 内部实现的,但如果在等待期间线程被外部中断,仍会抛出异常。示例:
java
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); Thread currentThread = Thread.currentThread(); // 设置超时任务:1秒后中断当前线程 scheduler.schedule(() -> currentThread.interrupt(), 1, TimeUnit.SECONDS); // 尝试获取锁,但1秒后会被中断 lock.tryLock(10, 30, TimeUnit.SECONDS); // 1秒后抛出InterruptedException
4. 在你的代码中的处理逻辑
当
tryLock()
被中断时,你的代码会:
- 恢复中断状态:
Thread.currentThread().interrupt()
- 返回错误结果:
Result.error("获取锁被中断")
这确保了:
- 调用者知道操作被中断
- 锁不会被误释放(因为未获取到锁)
- 线程的中断状态被正确标记,便于上层代码处理
总结
InterruptedException
在以下场景最可能出现:
- 用户主动取消操作(通过前端或管理接口触发)
- 系统资源回收(如线程池关闭)
- 超时控制(通过定时任务中断长时间运行的操作)
虽然在普通的业务流程中可能较少遇到,但在高并发、需要精细控制资源的系统中,这种中断处理是必要的。
3、说说redisson中出现的问题,以及解决方案:
引入了redis和redisson一直报错 连不上redis(其实连的上)
解决过程:
1、第一次用,不熟悉redis、redisson和配置文件 以为只需要配置一个redis的ip和端口公用
出现了上述问题
2、直接找一个redisson相关github项目自己跑 对比区别 发现配置文件错误(竟然有两个IP地址)