第一章 redisson框架
Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务
Redisson提供了使用Redis的最简单和最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。
更多介绍参考百度百科
源码地址:https://github.com/redisson/redisson/
官方文档:https://github.com/redisson/redisson/wiki/Redisson%E9%A1%B9%E7%9B%AE%E4%BB%8B%E7%BB%8D
1、redisson快速入门
这里我们使用spring-boot集成redission,首先需要在pom.xml文件中添加依赖
1 2 3 4 5 6 7 8 9
| <properties> <redisson-spring-boot>3.11.2</redisson-spring-boot> </properties>
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId> <version>${redisson-spring-boot}</version> </dependency>
|
在项目的resources目录中application.yml添加
1 2 3 4 5 6
| spring: redis: redisson: config: classpath:singleServerConfig.yaml
|
1.1、Single节点配置
配置单节点模式可以通过在resources目录中指定一个YAML格式的文件来实现。以下是YAML格式的配置文件样本。文件中的字段名称必须与singleServerConfig和config对象里的字段名称相符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| --- singleServerConfig: idleConnectionTimeout: 10000 pingTimeout: 1000 connectTimeout: 10000 timeout: 3000 retryAttempts: 3 retryInterval: 1500 reconnectionTimeout: 3000 failedAttempts: 3 password: null subscriptionsPerConnection: 5 clientName: null address: "redis://192.168.200.129:6379" subscriptionConnectionMinimumIdleSize: 1 subscriptionConnectionPoolSize: 50 connectionMinimumIdleSize: 32 connectionPoolSize: 64
threads: 8
nettyThreads: 8
codec: !<org.redisson.codec.JsonJacksonCodec> {}
transportMode: "NIO"
|
1.2、Cluster节点配置
配置集群模式可以通过指定一个YAML格式的文件来实现。以下是YAML格式的配置文件样本。文件中的字段名称必须与clusterServersConfig和config对象里的字段名称相符。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| --- clusterServersConfig: idleConnectionTimeout: 10000 connectTimeout: 10000 timeout: 3000 retryAttempts: 3 retryInterval: 1500 password: null subscriptionsPerConnection: 5 clientName: null loadBalancer: !<org.redisson.connection.balancer.RoundRobinLoadBalancer> {} slaveSubscriptionConnectionMinimumIdleSize: 1 slaveSubscriptionConnectionPoolSize: 50 slaveConnectionMinimumIdleSize: 32 slaveConnectionPoolSize: 64 masterConnectionMinimumIdleSize: 32 masterConnectionPoolSize: 64 readMode: "SLAVE" nodeAddresses: - "redis://192.168.200:129:7001" - "redis://192.168.200.129:7002" - "redis://192.168.200.129:7003" scanInterval: 1000 threads: 0 nettyThreads: 0 codec: !<org.redisson.codec.JsonJacksonCodec> {} "transportMode":"NIO"
|
2、redisson-分布式对象
上面我们集成了redission客户端,下面我们来看下他的基本使用
2.1、key操作相关
所有与Redis key相关的操作都归纳在RKeys,我们可以通过RedissonClient直接对keys进行操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| package com.itheima.redission.service;
import lombok.extern.slf4j.Slf4j; import org.redisson.api.RBucket; import org.redisson.api.RKeys; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component;
@Slf4j @Component public class KeyOpertions {
@Autowired RedissonClient redissonClient;
public void addData(){ for (int i = 0; i < 10; i++) { RBucket<Object> bucket = redissonClient.getBucket("security:aa"+i); bucket.set("itheima"+i); } }
public void foundedKeys(){ RKeys keys = redissonClient.getKeys(); Iterable<String> keysAll = keys.getKeys(); for (String key : keysAll) { log.info("获得key:"+key); } Iterable<String> redisKeys = keys.getKeysByPattern("security*"); for (String key : redisKeys) { log.info("获得key:"+key); } }
public void deleteKeys(){ RKeys keys = redissonClient.getKeys(); long flag = keys.delete("security:aa2","security:aa4"); log.info("批量删除key:security:aa2,security:aa4:{}",flag); flag = keys.deleteByPattern("security:aa*"); log.info("模糊删除key:security:aa*:{}",flag); }
}
|
2.2、通用对象桶
Redisson的分布式RBucket是一种通用对象桶可以用来存放任类型的对象,每个Redisson对象实例都会有一个与之对应的Redis数据实例,可以通过调用get***方法来取得Redis数据实例的名称(key),查看BucketOpertions 类中的方法BucketOper:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| package com.itheima.redission.service;
import com.itheima.redission.pojo.AnyObject; import lombok.extern.slf4j.Slf4j; import org.redisson.api.RBucket; import org.redisson.api.RBuckets; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component;
import java.util.Map; import java.util.concurrent.TimeUnit;
@Slf4j @Component public class BucketOpertions {
@Autowired RedissonClient redissonClient;
public void bucketOper(){
RBucket<AnyObject> anyObjectRBucket = redissonClient.getBucket("BucketOpertions"); AnyObject anyObject = AnyObject.builder() .name("张三") .age(19) .address("中国上海") .build(); anyObjectRBucket.set(anyObject); long timeToLive = anyObjectRBucket.remainTimeToLive(); log.info("BucketOperTest存活时间:{}",timeToLive);
anyObjectRBucket.set(anyObject,600, TimeUnit.SECONDS); timeToLive = anyObjectRBucket.remainTimeToLive(); log.info("BucketOperTest存活时间:{}",timeToLive/1000);
boolean trySetFlag = anyObjectRBucket.trySet(anyObject, 600, TimeUnit.SECONDS); log.info("试着为BucketOperTest存储元素:{}",trySetFlag);
AnyObject anyObjectNew = AnyObject.builder() .name("李四") .age(20) .address("中国北京") .build(); AnyObject anyObjectResult = anyObjectRBucket.getAndSet(anyObjectNew); log.info("BucketOperTest原始值:{}",anyObjectResult); anyObjectResult = anyObjectRBucket.get(); log.info("BucketOperTest新添值:{}",anyObjectResult);
boolean deleteFalg = anyObjectRBucket.delete(); log.info("BucketOperTest删除:{}",deleteFalg); }
public void bucketsOper(){ RBucket<AnyObject> bucketA = redissonClient.getBucket("BucketOpertionsTestA"); AnyObject anyObject = AnyObject.builder() .name("张三") .age(19) .address("中国上海") .build(); bucketA.set(anyObject); RBucket<AnyObject> bucketB = redissonClient.getBucket("BucketOpertionsTestB"); bucketB.set(anyObject);
RBuckets buckets = redissonClient.getBuckets(); Map<String, AnyObject> bucketsOperMap = buckets.get("BucketOpertionsTestA", "BucketOpertionsTestB"); log.info("map的元素信息:{}",bucketsOperMap); bucketA.delete(); bucketB.delete(); } }
|
还可以通过RBuckets接口实现批量操作多个RBucket对象,查看==BucketOpertions==类中的方法BucketsOper:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
public void BucketsOper(){ RBucket<AnyObject> bucketA=redissonClient.getBucket("BucketOperTestA"); AnyObject anyObject=AnyObject.builder() .name("张三") .age(19) .address("中国上海") .build(); bucketA.set(anyObject); RBucket<AnyObject> bucketB=redissonClient.getBucket("BucketOperTestB"); bucketB.set(anyObject);
RBuckets buckets=redissonClient.getBuckets(); Map<String, AnyObject> bucketsOperMap=buckets.get("BucketOperTestA", "BucketOperTestB"); log.info("map的元素信息:{}",bucketsOperMap); bucketsOperMap.clear();
}
|
2.3、原子整长形
Redisson的分布式整长形RAtomicLong与java.util.concurrent.atomic.AtomicLong对象类似
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| package com.itheima.redission.service;
import lombok.extern.slf4j.Slf4j; import org.redisson.api.RAtomicLong; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component;
@Slf4j @Component public class AtomicLongOpertions {
@Autowired RedissonClient redissonClient;
public void atomicLongOper(){ RAtomicLong atomicLongOper=redissonClient.getAtomicLong("AtomicLongOper"); atomicLongOper.set(0); long flag=atomicLongOper.get(); log.info("获得当前元素:{}",flag);
flag=atomicLongOper.incrementAndGet(); log.info("先递增1,然后返回元素:{}",flag);
flag=atomicLongOper.getAndIncrement(); log.info("先获得元素,再递增1",flag);
flag=atomicLongOper.get(); log.info("获得当前元素:{}",flag);
flag=atomicLongOper.decrementAndGet(); log.info("先递减1,然后返回元素:{}",flag);
flag=atomicLongOper.getAndDecrement(); log.info("先获得元素,再递减1",flag);
flag=atomicLongOper.get(); log.info("获得当前元素:{}",flag);
boolean delete=atomicLongOper.delete(); log.info("删除当前元素:{}",delete);
flag=atomicLongOper.addAndGet(2); log.info("添加并且获得元素:{}",flag);
flag=atomicLongOper.getAndDelete(); log.info("获得并且删除元素:{}",flag);
}
}
|
2.4、原子双精度浮点
Redisson还提供了分布式原子双精度浮点RAtomicDouble弥补了Java自身的不足
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| package com.itheima.redission.service;
import lombok.extern.slf4j.Slf4j; import org.redisson.api.RAtomicDouble; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component;
@Slf4j @Component public class AtomicDoubleOpertions {
@Autowired RedissonClient redissonClient;
public void atomicDoubleOper(){
RAtomicDouble atomicDoubleOper=redissonClient.getAtomicDouble("AtomicDoubleOper"); atomicDoubleOper.set(2.0D); double flag=atomicDoubleOper.get(); log.info("获得当前元素:{}",flag);
flag=atomicDoubleOper.incrementAndGet(); log.info("先递增1,然后返回元素:{}",flag);
flag=atomicDoubleOper.getAndIncrement(); log.info("先获得元素,再递增1",flag);
flag=atomicDoubleOper.get(); log.info("获得当前元素:{}",flag);
flag=atomicDoubleOper.decrementAndGet(); log.info("先递减1,然后返回元素:{}",flag);
flag=atomicDoubleOper.getAndDecrement(); log.info("先获得元素,再递减1",flag);
flag=atomicDoubleOper.get(); log.info("获得当前元素:{}",flag);
boolean delete=atomicDoubleOper.delete(); log.info("删除当前元素:{}",delete);
flag=atomicDoubleOper.addAndGet(2); log.info("添加并且获得元素:{}",flag);
flag=atomicDoubleOper.getAndDelete(); log.info("获得并且删除元素:{}",flag);
} }
|
3、redisson-分布式集合
3.1、RMap对象
基于Redis的Redisson的分布式映射结构的==RMap==对象实现了java.util.concurrent.ConcurrentMap
接口和java.util.Map
接口。与HashMap不同的是,RMap保持了元素的插入顺序。该对象的最大容量受Redis限制,最大元素数量是 4 294 967 295 个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| package com.itheima.redission.service;
import com.itheima.redission.pojo.AnyObject; import lombok.extern.slf4j.Slf4j; import org.redisson.api.RMap; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component;
import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set;
@Slf4j @Component public class RMapOpertions {
@Autowired RedissonClient redissonClient;
public void rMapOper(){
RMap<String, AnyObject> userInfo=redissonClient.getMap("userInfo"); AnyObject anyObjectA=AnyObject.builder().id("1").name("嬴政").age(22).address("秦朝").build(); AnyObject anyObjectB=AnyObject.builder().id("2").name("李斯").age(22).address("秦朝").build(); AnyObject anyObjectC=AnyObject.builder().id("3").name("孙悟空").age(22).address("唐").build(); userInfo.put(anyObjectA.getId(),anyObjectA); userInfo.put(anyObjectB.getId(),anyObjectB); userInfo.put(anyObjectC.getId(),anyObjectC);
Set<String> keySet=userInfo.readAllKeySet(); log.info("获得userInfo中所有的key:{}",keySet.toString());
Collection<AnyObject> anyObjects=userInfo.readAllValues(); log.info("获得userInfo中所有的值:{}",anyObjects.toString());
Set<Map.Entry<String, AnyObject>> entries=userInfo.readAllEntrySet(); log.info("获得userInfo中所有的元素对象:{}",entries.toString()); userInfo.clear();
userInfo.fastPut(anyObjectA.getId(),anyObjectA); userInfo.fastPut(anyObjectB.getId(),anyObjectB); userInfo.fastPut(anyObjectC.getId(),anyObjectC); userInfo.clear(); Map<String,AnyObject> map=new HashMap<>(); map.put(anyObjectA.getId(),anyObjectA); map.put(anyObjectB.getId(),anyObjectB); map.put(anyObjectC.getId(),anyObjectC); userInfo.putAll(map);
AnyObject anyObjectResult=userInfo.get(anyObjectA.getId()); log.info("根据辅key获得元素对象:{}",anyObjectResult.toString());
AnyObject anyObjectD=AnyObject.builder() .id("4").name("如来佛").age(1000000).address("上古").build(); AnyObject anyObject=userInfo.putIfAbsent(anyObjectD.getId(), anyObjectD); userInfo.clear();
} }
|
3.2、RMapCache对象
Redisson的分布式的==RMapCache==象在基于RMap的前提下实现了针对单个元素的淘汰机制。同时仍然保留了元素的插入顺序。由于RMapCache是基于RMap实现的,使它同时继承了java.util.concurrent.ConcurrentMap接口和java.util.Map接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| package com.itheima.redission.service;
import com.itheima.redission.pojo.AnyObject; import lombok.extern.slf4j.Slf4j; import org.redisson.api.RMap; import org.redisson.api.RMapCache; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component;
import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit;
@Slf4j @Component public class RMapCacheOpertions {
@Autowired RedissonClient redissonClient;
public void rMapCache(){
RMapCache<String, AnyObject> userInfo=redissonClient.getMapCache("userInfo"); AnyObject anyObjectA=AnyObject.builder().id("1").name("嬴政").age(22).address("秦朝").build(); AnyObject anyObjectB=AnyObject.builder().id("2").name("李斯").age(22).address("秦朝").build(); AnyObject anyObjectC=AnyObject.builder().id("3").name("孙悟空").age(22).address("唐").build(); userInfo.put(anyObjectA.getId(),anyObjectA,20, TimeUnit.SECONDS); userInfo.put(anyObjectB.getId(),anyObjectB,20, TimeUnit.SECONDS); userInfo.put(anyObjectC.getId(),anyObjectC,20, TimeUnit.SECONDS);
Set<String> keySet=userInfo.readAllKeySet(); log.info("获得userInfo中所有的key:{}",keySet.toString());
Collection<AnyObject> anyObjects=userInfo.readAllValues(); log.info("获得userInfo中所有的值:{}",anyObjects.toString());
Set<Map.Entry<String, AnyObject>> entries=userInfo.readAllEntrySet(); log.info("获得userInfo中所有的元素对象:{}",entries.toString()); userInfo.clear();
RMapCache<Long, OrderItemVo> mapCache = redissonClient.getMapCache("key"); OrderItemVo orderItemVo = mapCache.get("dishId"); mapCache.remove("dishId", orderItemVo);
} }
|
==注意:==目前的Redis自身并不支持散列(Hash)当中的元素淘汰,因此所有过期元素都是通过org.redisson.EvictionScheduler实例来实现定期清理的。为了保证资源的有效利用,每次运行最多清理300个过期元素。任务的启动时间将根据上次实际清理数量自动调整,间隔时间趋于1秒到1小时之间。比如该次清理时删除了300条元素,那么下次执行清理的时间将在1秒以后(最小间隔时间)。一旦该次清理数量少于上次清理数量,时间间隔将增加1.5倍
4、redisson-分布式锁
4.1、原理分析
加锁机制
线程去获取锁,获取成功: 执行lua脚本,保存数据到redis数据库。
线程去获取锁,获取失败: 一直通过while循环尝试获取锁,获取成功后,执行lua脚本,保存数据到redis
WatchDog自动延期机制
第一种情况:在一个分布式环境下,假如一个线程获得锁后,突然服务器宕机了,那么这个时候在一定时间后这个锁会自动释放,你也可以设置锁的有效时间(不设置默认30秒),这样的目的主要是防止死锁的发生
第二种情况:线程A业务还没有执行完,时间就过了,线程A 还想持有锁的话,就会启动一个watch dog后台线程,不断的延长锁key的生存时间
lua脚本
主要是如果你的业务逻辑复杂的话,通过封装在lua脚本中发送给redis,而且redis是单线程的,这样就保证这段复杂业务逻辑执行的原子性
4.2、基本使用
很明显RLock是继承Lock锁,所以他有Lock锁的所有特性,比如lock、unlock、trylock等特性,同时它还有很多新特性:强制锁释放,带有效期的锁,。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| public interface RRLock {
void lock();
void lock(long leaseTime, TimeUnit unit);
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException;
void unlock(); }
|
**lock()**:
- 此方法为加锁,但是锁的有效期采用默认30秒
- 如果主线程未释放,且当前锁未调用unlock方法,则进入到watchDog机制
- 如果主线程未释放,且当前锁调用unlock方法,则直接释放锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public void lock() throws InterruptedException{ log.info("线程:{},进入方法",Thread.currentThread().getName()); RLock rLock=redissonClient.getLock("lock"); rLock.lock(); long timeToLive=rLock.remainTimeToLive(); log.info("线程:{},获得锁,锁存活时间:{}S",Thread.currentThread().getName(),timeToLive/1000); Thread.sleep(2000); rLock.unlock(); log.info("线程:{},释放锁",Thread.currentThread().getName()); }
|
lock(long leaseTime, TimeUnit unit):
- 手动设置锁的有效时间
- 如果主线程未释放,且当前锁未调用unlock方法,则锁到期后会自动释放
- 如果主线程未释放,且当前锁调用unlock方法,则直接释放锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public void lockLaseTime() throws InterruptedException{ log.info("线程:{},进入方法",Thread.currentThread().getName()); RLock rLock=redissonClient.getLock("lockLaseTime"); rLock.lock(10,TimeUnit.SECONDS); long timeToLive=rLock.remainTimeToLive(); log.info("线程:{},获得锁,锁存活时间:{}S",Thread.currentThread().getName(),timeToLive/1000); Thread.sleep(2000); rLock.unlock(); log.info("线程:{},释放锁",Thread.currentThread().getName()); }
|
tryLock():
- 用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false,
- 如果主线程未释放,且当前锁未调用unlock方法,则进入到watchDog机制,
- 如果主线程未释放,且当前锁调用unlock方法,则直接释放锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public void tryLock() throws InterruptedException { log.info("线程:{},进入方法",Thread.currentThread().getName()); RLock rLock=redissonClient.getLock("tryLock"); boolean flag=rLock.tryLock(); if (flag){ long timeToLive=rLock.remainTimeToLive(); log.info("线程:{},获得锁,锁存活时间:{}S,加锁状态:{}",Thread.currentThread().getName(),timeToLive/1000,flag); Thread.sleep(2000); rLock.unlock(); log.info("线程:{},释放锁",Thread.currentThread().getName()); }else { log.info("线程:{},获得锁失败",Thread.currentThread().getName()); } }
|
tryLock(long time, TimeUnit unit):
- tryLock(long time, TimeUnit unit)方法和tryLock()方法是类似
- 区别在于这个方法在拿不到锁时会等待一定的时间, 在时间期限之内如果还拿不到锁,就返回false。
- 如果如果一开始拿到锁或者在等待期间内拿到了锁,则返回true
- 如果主线程未释放,且当前锁未调用unlock方法,则进入到watchDog机制
- 如果主线程未释放,且当前锁调用unlock方法,则直接释放锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public void tryLockWaitTime() throws InterruptedException { log.info("线程:{},进入方法",Thread.currentThread().getName()); RLock rLock=redissonClient.getLock("tryLockWaitTime"); boolean flag=rLock.tryLock(6, TimeUnit.SECONDS); if (flag){ long timeToLive=rLock.remainTimeToLive(); log.info("线程:{},获得锁,锁存活时间:{}S,加锁状态:{}",Thread.currentThread().getName(),timeToLive/1000,flag); Thread.sleep(10000); rLock.unlock(); log.info("线程:{},释放锁",Thread.currentThread().getName()); }else { log.info("线程:{},获得锁失败",Thread.currentThread().getName()); }
}
|
tryLock(long waitTime, long leaseTime, TimeUnit unit):比上面多一个参数,多添加一个锁的有效时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public void tryLockleasTime() throws InterruptedException { log.info("线程:{},进入方法",Thread.currentThread().getName()); RLock rLock = redissonClient.getLock("tryLockleasTime"); boolean flag = rLock.tryLock(11,10, TimeUnit.SECONDS); if (flag){ long timeToLive = rLock.remainTimeToLive(); log.info("线程:{},获得锁,锁存活时间:{}S,加锁状态:{}",Thread.currentThread().getName(),timeToLive/1000,flag); Thread.sleep(6000); rLock.unlock(); log.info("线程:{},释放锁",Thread.currentThread().getName()); }else { log.info("线程:{},获得锁失败",Thread.currentThread().getName()); } }
|