java如何使用redis加锁
作者:KLOCIC
这篇文章主要介绍了java如何使用redis加锁问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
java使用redis加锁
编写LockUtil工具类
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.connection.RedisStringCommands.SetOption; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.types.Expiration; import org.springframework.stereotype.Service; /** * LockUtil <br> * */ @Service public class LockUtil { @Autowired private RedisTemplate redisTemplate; @Autowired private StringRedisTemplate stringRedisTemplate; /** * @param lockKey 上锁的key * @param lockSeconds 上锁的秒数 * @return */ public boolean lock(String lockKey, int lockSeconds) { return (Boolean) redisTemplate.execute((RedisCallback) connection -> { byte[] key = lockKey.getBytes(); Boolean set = connection.set(key, key, Expiration.seconds(lockSeconds), SetOption.SET_IF_ABSENT); if (set == null) { return false; } return set; }); } public boolean isLock(String lockKey) { return stringRedisTemplate.opsForValue().get(lockKey)!=null; } public boolean clearLock(String lockKey){ return redisTemplate.delete(lockKey); } }
使用锁
public abstract class AbstractTask { @Autowired private LockUtil lockUtil; /** * 获取redis锁的key * * @return */ protected abstract String getLockKey(); protected boolean lock() { return lockUtil.lock(getLockKey(), 120); } protected boolean lockManual() { return lockUtil.lock(getLockKey(), 299); } protected boolean clearLock() { return lockUtil.clearLock(getLockKey()); } }
@Component @Slf4j @RefreshScope public class FileCapacityCountTask extends AbstractTask{ @Autowired private FileCapacityCountService fileCapacityCountService; @Scheduled(cron = "${batch.verification.schedule.capacity}") public void task(){ if (!lock()) { log.info("本实例无需执行定时任务"); return; } fileCapacityCountService.fileCapacityCountTask(); } @Override protected String getLockKey() { String today = DateUtil.formatDate(new Date()); return FileCapacityCountTask.class.getSimpleName() + CommonConstant.APPLICATION_NAME + today; } }
redis锁用法java代码
由于redis是串行的,所以可以用redis实现锁机制。
下方是java代码
@Component @Slf4j public class RedisSingleLock { private final StringRedisTemplate redis; public SimpleDistributedLock(StringRedisTemplate redis) { this.redis = redis; } //这个方法,可以传入key加锁;多线程调用时,只有1个能获取锁成功,其它线程则会进入循环,不停尝试获取锁 public void lock(String key) { do { Boolean lockSuccess = redis.opsForValue().setIfAbsent(key, "1", 1, TimeUnit.DAYS); if (lockSuccess == null) { throw new IllegalStateException(); } if (!lockSuccess) { try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { log.error(e.getMessage(), e); } } else { break; } } while (true); } //这个方法,传入key释放锁,当持有锁的线程执行业务代码完毕后调用,释放这个锁;上方某一个在lock方法中循环尝试获得锁的线程可以获得锁,另外的线程则继续循环等待 public void releaseLock(String key) { redis.delete(key); } //这个方法只尝试获取一次锁,返回获取结果 public boolean tryLock(String key) { Boolean lockSuccess = redis.opsForValue().setIfAbsent(key, "1", 1, TimeUnit.DAYS); if (lockSuccess == null) { throw new IllegalStateException(); } return lockSuccess; } }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。