package com.dobbinsoft.fw.support.component; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import java.time.Duration; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; /** * Created with IntelliJ IDEA. * Description: * User: rize * Date: 2019-02-07 * Time: 上午11:40 */ @Component public class LockComponent { @Autowired private StringRedisTemplate lockRedisTemplate; @Autowired(required = false) private BeforeGetLockKey beforeGetLockKey; private static final String LOCK_PREFIX = "LOCK_PREFIX_"; /** * 获取乐观锁 * * @param key * @param timeoutSec 锁过期时间 * @return */ public boolean tryLock(String key, Integer timeoutSec) { return lockRedisTemplate.opsForValue().setIfAbsent(LOCK_PREFIX + getKey(key), System.currentTimeMillis() + "", Duration.ofSeconds(timeoutSec)); } /** * 阻塞获取锁 * * @param key * @param timeoutSec * @return */ public boolean lockBlock(String key, Integer timeoutSec) { boolean res; long startTime = System.currentTimeMillis(); do { res = lockRedisTemplate.opsForValue().setIfAbsent(LOCK_PREFIX + getKey(key), startTime+ "", Duration.ofSeconds(timeoutSec)); try { Thread.sleep(20); } catch (InterruptedException e) { } } while (!res && ((System.currentTimeMillis() - startTime) / 1000 > timeoutSec)); return res; } public boolean tryLockMulti(Collection keys, Integer timeoutSec) { Map map = new HashMap<>(); String now = System.currentTimeMillis() + ""; for (String key : keys) { map.put(getKey(key), now); } boolean suc = lockRedisTemplate.opsForValue().multiSetIfAbsent(map); if (suc) { keys.forEach(item -> { lockRedisTemplate.expire(item, timeoutSec, TimeUnit.SECONDS); }); } return suc; } public void release(String key) { lockRedisTemplate.delete(LOCK_PREFIX + getKey(key)); } public boolean hashPut(String table, String key) { return lockRedisTemplate.opsForHash().putIfAbsent(table, getKey(key), key); } public boolean hashContains(String table, String key) { return lockRedisTemplate.opsForHash().hasKey(table, getKey(key)); } public void hashDel(String table, String key) { lockRedisTemplate.opsForHash().delete(table, getKey(key)); } private String getKey(String key) { if (beforeGetLockKey != null) { return beforeGetLockKey.getKey(key); } return key; } }