基于redis的 分布式锁 Java实现
package com.rynk.mugua.trading.biz.commons.lock; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; import javax.annotation.Resource; import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit; /**
* 分布式锁
*
* @author ZHANGYUKUN
*
*/
@Component
public class DistributedLockHandler { private static final Logger logger = LoggerFactory.getLogger(DistributedLockHandler.class); /**
* 最大持有锁的时间(毫秒)
*/
private final static long LOCK_EXPIRE = 30 * 1000L; /**
* 尝试获取锁的时间间隔(毫秒)
*/
private final static long LOCK_TRY_INTERVAL = 30L; /**
* 获取锁最大等待时间( 毫秒 )
*/
private final static long LOCK_TRY_TIMEOUT = 20 * 1000L; @Resource// (name = "customRedisTemplate")
private RedisTemplate<String, String> template; /**
* 尝试获取 分布式锁
*
* @param lockKey
* 锁名
* @return true 得到了锁 ,false 获取锁失败
*/
public boolean tryLock(String lockKey) {
return getLock(lockKey, LOCK_TRY_TIMEOUT, LOCK_TRY_INTERVAL, LOCK_EXPIRE);
} /**
* 尝试获取 分布式锁(不自动释放锁)
*
* @param lockKey
* 锁名
* @return true 得到了锁 ,false 获取锁失败
*/
public boolean tryLockNotAutoRelease(String lockKey) {
return getLock(lockKey, LOCK_TRY_TIMEOUT, LOCK_TRY_INTERVAL, -1);
} /**
* 尝试获取 分布式锁
*
* @param lockKey
* 锁名
* @param timeout
* 获取锁最大等待时间
* @return true 得到了锁 ,false 获取锁失败
*/
public boolean tryLock(String lockKey, long timeout) {
return getLock(lockKey, timeout, LOCK_TRY_INTERVAL, LOCK_EXPIRE);
} /**
* 尝试获取 分布式锁(不自动释放锁)
*
* @param lockKey
* 锁名
* @param timeout
* 获取锁最大等待时间
* @return true 得到了锁 ,false 获取锁失败
*/
public boolean tryLockNotAutoRelease(String lockKey, long timeout) {
return getLock(lockKey, timeout, LOCK_TRY_INTERVAL, -1);
} /**
* 尝试获取 分布式锁
*
* @param lockKey
* 锁名
* @param timeout
* 获取锁最大等待时间
* @param tryInterval
* 获取锁尝试 时间间隔
* @return true 得到了锁 ,false 获取锁失败
*/
public boolean tryLock(String lockKey, long timeout, long tryInterval) {
return getLock(lockKey, timeout, tryInterval, LOCK_EXPIRE);
} /**
* 尝试获取 分布式锁(不释放锁)
*
* @param lockKey
* 锁名
* @param timeout
* 获取锁最大等待时间
* @param tryInterval
* 获取锁尝试 时间间隔
* @return true 得到了锁 ,false 获取锁失败
*/
public boolean tryLockNotAutoRelease(String lockKey, long timeout, long tryInterval) {
return getLock(lockKey, timeout, tryInterval, -1);
} /**
* 尝试获取 分布式锁
*
* @param lockKey
* 锁名
* @param timeout
* 获取锁最大等待时间
* @param tryInterval
* 获取锁尝试 时间间隔
* @param lockExpireTime
* 锁最大持有时间
* @return true 得到了锁 ,false 获取锁失败
*/
public boolean tryLock(String lockKey, long timeout, long tryInterval, long lockExpireTime) {
return getLock(lockKey, timeout, tryInterval, lockExpireTime);
} /**
* 获取分布式锁
*
* @param lockKey
* 锁名
* @param timeout
* 获取锁最大等待时间
* @param tryInterval
* 获取锁尝试 时间间隔
* @param lockExpireTime
* 锁最大持有时间
* @return true 得到了锁 ,false 获取锁失败
*/
private boolean getLock(String lockKey, long timeout, long tryInterval, long lockExpireTime) {
try {
if (StringUtils.isEmpty(lockKey)) {
return false;
}
long startTime = System.currentTimeMillis();
do {
ValueOperations<String, String> ops = template.opsForValue();
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); if (lockExpireTime > 0) {
if (ops.setIfAbsent(lockKey, sd.format(new Date()),lockExpireTime, TimeUnit.MILLISECONDS )) {
return true;
}
}else {
if (ops.setIfAbsent(lockKey, sd.format(new Date()) )) {
return true;
}
} Thread.sleep(tryInterval);
} while (System.currentTimeMillis() - startTime < timeout);
} catch (InterruptedException e) {
logger.error(e.getMessage());
return false;
}
return false;
} /**
* 释放锁
*
* @param lockKey
*/
public void unLock(String lockKey) {
if (!StringUtils.isEmpty(lockKey)) {
if( template.hasKey(lockKey) ) {
template.delete(lockKey);
}
}
} }
测试代码:启动 100 个线程 并发的 个 a 加1 ,如果 如果 能锁住 ,那么 100 个线程会排队 逐步打印 0 到 99.
@Autowired
DistributedLockHandler lock;
ExecutorService executorService = Executors.newFixedThreadPool(1000);
int a= 0;
@PostMapping("/t1")
@ApiOperation(value = "t1")
public CommonResult<String> t1( BigDecimal scale) {
String key = "key1";
for( int i=0;i<100;i++ ) {
executorService.execute( ()->{
try {
if( lock.tryLock( key ) ) {
System.out.println("得到" + a );
a++;
}
}catch (Exception e) {
e.printStackTrace();
}finally {
lock.unLock(key);
}
} );
}
a = 0;
return CommonResult.getSucceedInstance();
}
结果截图:



基于redis的 分布式锁 Java实现的更多相关文章
- Java基于redis实现分布式锁(SpringBoot)
前言 分布式锁,其实原理是就是多台机器,去争抢一个资源,谁争抢成功,那么谁就持有了这把锁,然后去执行后续的业务逻辑,执行完毕后,把锁释放掉. 可以通过多种途径实现分布式锁,例如利用数据库(mysql等 ...
- 基于 Redis 的分布式锁
前言 分布式锁在分布式应用中应用广泛,想要搞懂一个新事物首先得了解它的由来,这样才能更加的理解甚至可以举一反三. 首先谈到分布式锁自然也就联想到分布式应用. 在我们将应用拆分为分布式应用之前的单机系统 ...
- 基于redis的分布式锁(转)
基于redis的分布式锁 1 介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分 ...
- 基于redis的分布式锁实现
1.分布式锁介绍 在计算机系统中,锁作为一种控制并发的机制无处不在. 单机环境下,操作系统能够在进程或线程之间通过本地的锁来控制并发程序的行为.而在如今的大型复杂系统中,通常采用的是分布式架构提供服务 ...
- 基于redis的分布式锁(不适合用于生产环境)
基于redis的分布式锁 1 介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分 ...
- redis系列:基于redis的分布式锁
一.介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分为两部分,一个是单机环境, ...
- 基于redis的分布式锁的分析与实践
前言:在分布式环境中,我们经常使用锁来进行并发控制,锁可分为乐观锁和悲观锁,基于数据库版本戳的实现是乐观锁,基于redis或zookeeper的实现可认为是悲观锁了.乐观锁和悲观锁最根本的区别在于 ...
- [Redis] 基于redis的分布式锁
前言分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁. 可靠性首先,为了确保 ...
- 从零到一手写基于Redis的分布式锁框架
1.分布式锁缘由 学习编程初期,我们做的诸如教务系统.成绩管理系统大多是单机架构,单机架构在处理并发的问题上一般是依赖于JDK内置的并发编程类库,如synchronize关键字.Lock类等.随着业务 ...
随机推荐
- IDEA spirng boot @Autowired注解 mapper出现红色下划线解决方法
如图所示,解决方法为: 把勾去掉即可.
- 【转】 C++析构函数的作用和用法
转自:https://www.cnblogs.com/puyangsky/p/5319470.html 一.定义1. 作用:对象消亡时,自动被调用,用来释放对象占用的空间2.特点: (1) 名字与 ...
- LeetCode--018--四数之和(java)
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满 ...
- Vue-Router + Vuex 实现单页面应用
效果查看(一个食品安全网,大家也可以发布一些食品安全的见闻,尽举手之劳): 源代码:https://pan.baidu.com/s/1i43H3LV 如果想要服务器端代码可以在评论里说明一下 利用vu ...
- .NET学习日记【1】
不得不说,之前一年学习的内容基本上在第一章中都有所涉及,而且还讲了很多不知道知识.看完第一张对多态和继承都多了一些体会.在1.4前面的都有很认证的看过,也在vs上面验证了一下.然后也明白了.NET到底 ...
- [uva P1601] The Morning after Halloween
[uva P1601] The Morning after Halloween 题目链接 非常经典的一道题目,lrj的书上也有(貌似是紫书?). 其实这题看起来就比较麻烦.. 首先要保证小鬼不能相遇, ...
- Qt-Designer打不开
安装Qt后双击桌面的Designer没有反应,解决办法就是将安装路径里的qwebengineview.dll文件后缀名加个".bak".
- caffe安装
安装caffe的时候一定要保持一个乐观的心态,不然容易放弃人生.由于自己是装完才写的,所以并没有截图. 平台:Window7 硬件:NVIDIV quaro M4000 软件:Visual Studi ...
- 全面了解TCP/IP到HTTP
一.OSI参考模型 OSI(Open System Interconnect),即开放式系统互联.一般都叫OSI参考模型,是ISO(国际标准化组织)组织在1985年研究的网络互联模型.该体系结构标准定 ...
- 使用 udev 高效、动态地管理 Linux 设备文件
本文转自:https://www.ibm.com/developerworks/cn/linux/l-cn-udev/index.html 概述: Linux 用户常常会很难鉴别同一类型的设备名,比如 ...