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();
}
结果截图: