菜单
登录注册
欢 迎
登录
自动登录
忘记密码?
新朋友
注册
注册
老朋友
登录
笔记内容为空!
TA的笔记树 >>
java基于spring.redisTemplate实现分布式锁工具类
Java工具类
### 工具类 ``` import javafx.util.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.core.BoundValueOperations; import org.springframework.data.redis.core.StringRedisTemplate; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; public class RedisLock { private static final Logger LOG = LoggerFactory.getLogger(RedisLock.class); private static final String LOCKED = "LOCKED"; // 存储到redis中的锁标志 private volatile boolean isLocked = false; private StringRedisTemplate redisTemplate; private String key; private TimeUnit lockTimeoutAndExpireTimeUnit = TimeUnit.SECONDS; private int getLockTimeout = 10; // 请求锁的超时时间 private int lockExpire = 30; // 获取到锁后,设置锁过期时间 private int sleepMillis = 100; // 每次请求失败休眠时间(毫秒) /** * @param redisTemplate Redis管理模板 * @param key 锁定key * @param lockTimeoutAndExpireTimeUnit [获取锁超时/锁失效]对应的TimeUnit(默认:TimeUnit.SECONDS) * @param getLockTimeout 锁过期时间(避免程序问题而一直持有锁) * @param lockExpire 请求锁超时时间 * @param sleepMillis 每次请求锁失败最少休眠时间(毫秒) */ public RedisLock(StringRedisTemplate redisTemplate, String key, TimeUnit lockTimeoutAndExpireTimeUnit, int getLockTimeout, int lockExpire, int sleepMillis) { if (redisTemplate == null) { throw new RuntimeException("redis锁StringRedisTemplate不能为null"); } if (key == null || "".equals(key.trim())) { throw new RuntimeException("redis锁的key不能为空"); } this.redisTemplate = redisTemplate; this.key = key; if (lockTimeoutAndExpireTimeUnit != null) { this.lockTimeoutAndExpireTimeUnit = lockTimeoutAndExpireTimeUnit; } if (getLockTimeout > 0) { this.getLockTimeout = getLockTimeout; } if (lockExpire > 0) { this.lockExpire = lockExpire; } if (sleepMillis > 0) { this.sleepMillis = sleepMillis; } } public RedisLock(StringRedisTemplate redisTemplate, String key, int getLockTimeout, int lockExpire, int sleepMillis) { this(redisTemplate, key, null, getLockTimeout, lockExpire, sleepMillis); } public RedisLock(StringRedisTemplate redisTemplate, String key, TimeUnit lockTimeoutAndExpireTimeUnit, int getLockTimeout, int lockExpire) { this(redisTemplate, key, lockTimeoutAndExpireTimeUnit, getLockTimeout, lockExpire, 0); } public RedisLock(StringRedisTemplate redisTemplate, String key, int getLockTimeout, int lockExpire) { this(redisTemplate, key, null, getLockTimeout, lockExpire, 0); } public RedisLock(StringRedisTemplate redisTemplate, String key, int sleepMillis) { this(redisTemplate, key, null, 0, 0, sleepMillis); } public RedisLock(StringRedisTemplate redisTemplate, String key) { this(redisTemplate, key, null, 0, 0, 0); } public static
Pair
lockedWork(RedisLock redisLock, Supplier
worker) { return lockedWork(redisLock, 0, 0, worker); } /** * @param redisLock 分布式锁对象 * @param addSleepTimeMillis 每次获取锁失败后叠加等待时间 * @param maxSleepTimeMillis 叠加等待时间的最大时间,超过则不再叠加 * @param worker 获取到锁后的业务处理函数 * @param
* * @return */ public static
Pair
lockedWork(RedisLock redisLock, int addSleepTimeMillis, int maxSleepTimeMillis, Supplier
worker) { if (redisLock == null || worker == null) { throw new RuntimeException("本地锁或redisLock对象或锁内程序不能为空"); } if (!redisLock.lock(addSleepTimeMillis, maxSleepTimeMillis)) { LOG.error(String.format("未获取到锁,任务取消,锁:%s", redisLock.key)); return new Pair<>(false, null); } LOG.warn(String.format("已获取到锁,开始执行锁内程序,锁:%s", redisLock.key)); try { return new Pair<>(true, worker.get()); } finally { redisLock.unlock(); LOG.warn(String.format("释放锁:%s", redisLock.key)); } } public static void main(String[] args) { Pair
result = RedisLock.lockedWork( new RedisLock(null, "lockKey"), () -> { // 锁内程序 return "我是锁内程序执行结果"; } ); if (result.getKey()) { System.out.println("锁内程序成功调用,并返回数据:" + result.getValue()); } else { System.out.println("未获取到锁"); } } private boolean lock() { return this.lock(0, 0); } /** * 获取锁 * * @param addSleepTimeMillis 递增睡眠时间 * @param maxSleepTimeMillis 最大睡眠时间 * * @return */ private boolean lock(int addSleepTimeMillis, int maxSleepTimeMillis) { if (maxSleepTimeMillis < sleepMillis) maxSleepTimeMillis = sleepMillis; if (addSleepTimeMillis < 0) addSleepTimeMillis = 0; BoundValueOperations
ops = this.redisTemplate.boundValueOps(key); long timeout = TimeUnit.MILLISECONDS.convert(this.getLockTimeout, lockTimeoutAndExpireTimeUnit); long expire = TimeUnit.MILLISECONDS.convert(this.lockExpire, lockTimeoutAndExpireTimeUnit); long startTime = System.currentTimeMillis(); int currSleepMillis = sleepMillis; while ((System.currentTimeMillis() - startTime) < timeout) { try { if (ops.setIfAbsent(LOCKED)) { this.redisTemplate.expire(key, expire, TimeUnit.MILLISECONDS); this.isLocked = true; break; } else if (ops.getExpire() == -1L) { this.redisTemplate.expire(key, expire, TimeUnit.MILLISECONDS); LOG.error("检测到已存在的锁未设置失效时间,为其设置失效时间,key:" + key); } if (currSleepMillis > maxSleepTimeMillis) currSleepMillis = maxSleepTimeMillis; LOG.warn(String.format("未获取到锁,%s,休眠:%s毫秒,key:%s", Thread.currentThread(), currSleepMillis, key)); TimeUnit.MILLISECONDS.sleep(currSleepMillis); currSleepMillis = currSleepMillis + addSleepTimeMillis; } catch (Exception e) { LOG.error("", e); } } return this.isLocked; } private void unlock() { if (this.isLocked) { this.redisTemplate.delete(key); } } } ```
vanki
我是那么喜欢夏日的花影。每每走在路上,耳朵里灌着人声、车声、蝉鸣声,我仍不觉得聒噪,因为路上总有花树,总有花影,清清凉凉,被风抚着,清幽解暑。
浏览:
7813
创建:
2018-09-14 01:00:14
更新:
2020-08-20 14:51:13
TA的最新笔记
spring-boot配置redis多数据源
linux源修改(阿里)
python安装postgresql依赖
arthas使用
java基于spring的NamedParameterJdbcTemplate封装的获取sql工具类
Impala添加负载
S3常用使用
redis常用操作
hdfs相关命令
crontab使用
TA的最热笔记
java异步http请求工具类(org.asynchttpclient)
iTerm2主题配置与常用技巧
java基于spring.redisTemplate实现分布式锁工具类
Kotlin + SpringBoot + JPA(Hibernate) + Repository自定义方法
IDEA汉化
Sequel Pro连接mysql8打开数据库报错
centos-Hadoop2.7.3完全分布式搭建(HA)
SpringBoot上传文件报错(The temporary upload location [..] is not valid)
mac常用软件
kotlin对象属性值拷贝工具类