发布于2021-03-13 15:03 阅读(589) 评论(0) 点赞(26) 收藏(0)
1
Redisson 是 redis 的一个Java客户端,但是最为人熟知的是它的分布式锁的功能。所以分布式锁就不要自己实现一套了,人家帮你实现了并且考虑得比你周全得多代码健壮得多。
2
Redisson 除了所熟知的分布式锁的功能,其实也跟其他的Redis的Java客户端一样,有操作redis的功能,例如
// string类型的,key是abc,值是vvv
RBucket<String> s = redissonClient.getBucket("abc");
s.set("vvv");
它提供的Java API看起来是有点奇怪,其实更加面向对象。
为什么不自己写分布式锁?你写的分布式锁可能无法实现 “A线程持有锁的时候B线程阻塞在那里等待直至获得”,你写的可能就是 “B线程尝试一次是否能获取”。Redisson 实现比较复杂,实现了java.util.concurrent.locks.Lock(JUC包的,跟你用的ReentrantLock是一样的)
引入需要的包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.3.9.RELEASE</version>
</dependency>
<!-- 奇怪,网上的一个列子,引用了redisson,但是还引用了 spring-boot-starter-data-redis,不是平行的东西吗? 不懂-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.11.4</version>
</dependency>
配置
# Redis数据库索引(默认为0)
spring.redis.database=15
spring.redis.host=47.103.66.213
spring.redis.port=6379
spring.redis.password=xxxx
Java代码
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private RedissonClient redissonClient;
@GetMapping("/submitOrder")
public String submitOrder() {
RLock lock = redissonClient.getLock(product);
try {
lock.lock();//阻塞
// boolean b = lock.tryLock();//非阻塞
int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));
if (stock > 0) {
//下单
stock -= 1;
stringRedisTemplate.opsForValue().set("stock", String.valueOf(stock));
System.out.println("扣减成功,库存stock:" + stock);
} else {
//没库存
System.out.println("扣减失败,库存不足");
}
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();//释放锁
}
}
return "end";
}
lock():会阻塞,一直等到能获得锁。无返回值
lock(long leaseTime, TimeUnit timeUnit):会阻塞,设定租期,租期到后自动释放锁。无返回值
tryLock():不阻塞,只检查一次,即只检查当前时刻能否获得锁。返回boolean
tryLock(long time, TimeUnit unit):在设定的time(等待时间)内阻塞,如果能获得锁则立即返回true,超过等待时间仍不能获得则返回false
tryLock(long waitTime, long leaseTime, TimeUnit unit):设定了等待时间以及租期
unlock():释放锁,如果已经是释放状态则会抛出异常(例如其他线程已经释放,或者租期到释放),只能是持有锁的线程进行释放否则抛出异常。
isLock():判断锁是否被占用。注意:不是判断锁是否被当前线程占用,锁被其他线程占用的情况也会返回true
isHeldByCurrentThread():判断锁是否被当前线程占用。这个才是判断锁是否被当前线程占用(持有)
其他注意:unlock() 之前最好判断是否锁被占用,才进行解锁
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
注意不要这么用,因为所不被当前线程持有 isLocked()也返回true,但是unlock()必须是当前线程持有才不会抛出异常
if (lock.isLocked()) {
lock.unlock();
}
总结:
看上面的例子,可以看到 stringRedisTemplate
和 redissonClient
是混着用的,确实可以混着用,毕竟很多人不熟悉 Redisson 的API,仅仅将 Redisson 作为分布式锁的工具,操作 redis 依然保持不变是没问题的。
但是注意一下下面的混用会出错的
// 混用会报错
stringRedisTemplate.opsForValue().set("t3", "f_v", 100, TimeUnit.SECONDS);
RBucket<String> s = redissonClient.getBucket("t3");
String value = s.get();
原文链接:https://blog.csdn.net/w8y56f/article/details/114699555
作者:飞翔公园
链接:http://www.javaheidong.com/blog/article/114773/43a62655775d8c5b6600/
来源:java黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 java黑洞网 All Rights Reserved 版权所有,并保留所有权利。京ICP备18063182号-2
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!