java如何使用redis加锁

 更新时间:2023年01月09日 16:54:26   作者: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;
    }
}

    

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • springboot项目如何设置session的过期时间

    springboot项目如何设置session的过期时间

    这篇文章主要介绍了springboot项目如何设置session的过期时间,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Jackson自定义序列化与反序列化注解详解

    Jackson自定义序列化与反序列化注解详解

    这篇文章主要介绍了Jackson自定义序列化与反序列化注解详解,某些场景下,我们使用Jackson对数据进行序列化或反序列化的时候,需要对某些数据进行特殊处理,需要的朋友可以参考下
    2023-11-11
  • Java如何通过Socket同时发送文本和文件

    Java如何通过Socket同时发送文本和文件

    这篇文章主要介绍了Java如何通过Socket同时发送文本和文件问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • SpringBoot Mybatis Plus公共字段自动填充功能

    SpringBoot Mybatis Plus公共字段自动填充功能

    这篇文章主要介绍了SpringBoot Mybatis Plus公共字段自动填充功能的相关资料,需要的朋友可以参考下
    2017-04-04
  • SpringBoot配置Email发送功能实例

    SpringBoot配置Email发送功能实例

    本篇文章主要介绍了SpringBoot配置Email发送功能实例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • java.util.concurrent.ExecutionException 问题解决方法

    java.util.concurrent.ExecutionException 问题解决方法

    这篇文章主要介绍了java.util.concurrent.ExecutionException 问题解决方法的相关资料,需要的朋友可以参考下
    2016-11-11
  • springboot读取nacos配置文件的实现

    springboot读取nacos配置文件的实现

    SpringBoot注册服务到Nacos上,由Nacos来做服务的管理,本文主要介绍了springboot读取nacos配置文件的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • Hibernate连接三种数据库的配置文件

    Hibernate连接三种数据库的配置文件

    今天小编就为大家分享一篇关于Hibernate连接三种数据库的配置文件,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • SpringBoot彩色日志配置方式

    SpringBoot彩色日志配置方式

    这篇文章主要介绍了SpringBoot彩色日志配置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • SpringBoot拦截器的使用介绍

    SpringBoot拦截器的使用介绍

    大家好,本篇文章主要讲的是SpringBoot拦截器的使用介绍,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01

最新评论