java高频面试题-高级篇

1,什么是乐观锁和悲观锁?在项目中哪些地方可以用到?


    乐观锁和悲观锁是在并发编程中用于处理数据一致性和并发控制的两种不同策略。
    乐观锁:    乐观锁的基本思想是乐观地认为在数据处理过程中不会发生冲突,直到提交数据时才会检查是否有冲突。通常是通过版本号或时间戳等方式实现    当多个用户同时访问同一数据时,系统会先读取数据并记录版本号或时间戳,然后在更新数据时检查版本号或时间戳是否一致。如果一致,则提交更新;如果不一致,则认为数据已经被其他用户修改过,需要进行冲突处理。
    
    悲观锁:    悲观锁的基本思想是悲观地认为在数据处理过程中会发生冲突,因此在访问数据时会进行加锁操作,确保同一时刻只有一个用户能够对数据进行操作。悲观锁通常通过数据库的行级锁或表级锁来实现,也可以通过编程语言的锁机制来实现。
    
    在项目中,乐观锁和悲观锁可以用于以下场景:
    乐观锁:
        在电子商务系统中,用于处理商品库存的更新。多个用户同时购买同一商品时,需要保证库存的正确性。
        在博客系统中,用于处理文章的编辑和保存。多个用户同时编辑同一篇文章时,需要保证数据的一致性。
    悲观锁:
        在银行系统中,用于处理账户转账操作。确保同一时刻只有一个用户能够修改账户余额,防止数据错误。
        在在线预订系统中,用于处理座位的预订。确保同一时刻只有一个用户能够选择座位,避免冲突。
    乐观锁适用于并发量较低、冲突发生概率较小的场景,而悲观锁适用于并发量较高、冲突发生概率较高的场景。


    
2,什么叫redis缓存雪崩、击穿、穿透?


    缓存雪崩:    缓存雪崩是指在某个时间点,大量缓存数据同时失效或被清理,导致大量请求直接访问数据库或其他后端系统,引起系统压力剧增,甚至导致系统崩溃。
    解决方案:设置不同的缓存失效时间,使用多级缓存架构,保证缓存的高可用性。
    
    缓存击穿:
    缓存击穿是指针对某个热点数据,缓存失效时,大量请求同时访问该数据,导致请求直接访问数据库或其他后端系统,引起系统压力剧增。
    解决方案:使用互斥锁或分布式锁,保证只有一个请求能够重新加载缓存数据,其他请求等待。
    
    缓存穿透:
    缓存穿透是指请求查询一个不存在的数据,由于缓存中没有该数据,每次请求都会直接访问数据库或其他后端系统,导致系统压力增加。
    解决方案:使用布隆过滤器或空对象缓存,拦截无效请求,避免直接访问后端系统。
    实际项目中,为了避免缓存雪崩、缓存击穿和缓存穿透等问题的发生,需要合理设置缓存失效时间、使用互斥锁或分布式锁、进行数据预热等措施,保证系统的稳定性和性能。


    
3,SpringBoot的常用注解有哪些?有没有自己写过注解?


    控制器注解:
    @RestController: 声明一个控制器类,返回的数据直接写入 HTTP 响应体中。
    @RequestMapping: 映射 HTTP 请求到处理方法。
    @GetMapping, @PostMapping, @PutMapping, @DeleteMapping: 分别对应 HTTP 的 GET、POST、PUT、DELETE 请求。
    
    依赖注入注解:
    @Autowired: 自动装配 Bean。
    @Value: 注入配置文件中的属性值。
    @Qualifier: 指定具体的 Bean。
    
    数据校验注解:
    @Valid: 开启数据校验。
    @NotNull, @NotEmpty, @NotBlank: 验证字段是否为 null、空、非空白字符。
    
    事务管理注解:
    @Transactional: 开启事务管理。
    
    AOP 注解:
    @Aspect: 声明一个切面。
    @Before, @After, @Around: 定义切面的通知类型。
    
    定时任务注解:
    @Scheduled: 定时任务注解。
    
    缓存注解:
    @Cacheable, @CachePut, @CacheEvict: 用于缓存数据的注解。
    
    自定义注解:
    在一个项目中曾经自定义过注解。在该项目中,我定义了一个 @AuditLog注解,用于标记需要记录操作日志的方法。通过在方法上添加@AuditLog注解,    系统会自动记录该方法的调用信息,包括操作用户、操作时间、操作内容等,方便后续的审计和监控。
    自定义注解可以有效简化代码逻辑,提高代码的可读性和可维护性。


    
4,如何实现分布式锁?


    基于数据库实现分布式锁:
    在数据库中创建一张表,用来存储锁的信息,包括锁的名称、持有者、过期时间等。
    使用数据库的事务特性和唯一索引来实现锁的互斥性。
    可以通过定时任务或心跳机制来续约锁的过期时间,避免锁被意外释放。
    
    基于缓存实现分布式锁:
    使用分布式缓存如 Redis、Memcached 来存储锁的信息。
    利用缓存的原子性操作(如 SETNX、SETEX)来实现锁的互斥性。
    可以设置锁的过期时间,避免锁被长时间占用。
    
    基于 ZooKeeper 实现分布式锁:
    使用 ZooKeeper 的临时顺序节点来实现分布式锁。
    客户端创建一个临时顺序节点,节点的序号最小的客户端获取锁。
    当客户端释放锁时,对应的临时节点也会被删除,其他客户端可以获取锁。
    
    基于 Redisson 等框架实现分布式锁:
    Redisson 是一个基于 Redis 的 Java 驻内存数据网格(In-Memory Data Grid)和分布式锁服务。
    Redisson 提供了简单易用的 API,可以方便地实现分布式锁、信号量、队列等功能。
    
    最后,无论使用哪种方式,实现分布式锁都需要考虑锁的互斥性、可重入性、死锁避免、锁超时处理等问题。
    同时,需要注意锁的粒度和范围,避免锁的持有时间过长导致性能问题。

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值