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);
			}
		}
	}

}
  • 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.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.
  • 194.
  • 195.

  

 

 

 

 

 

测试代码:启动 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();
	}
  • 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.

 

 

结果截图:  

基于redis的 分布式锁  Java实现_时间间隔

 

 

 

基于redis的 分布式锁  Java实现_分布式锁_02

 

 

基于redis的 分布式锁  Java实现_时间间隔_03