java如何使用redis加锁

2023-01-09 17:37:08

目录java使用redis加锁编写LockUtil工具类使用锁redis锁用法java代码下方是java代码总结java使用redis加锁编写LockUtil工具类importorg.springf...

目录
Java使用Redis加锁
编写LockUtil工具类
使用锁
redis锁用法java代码
下方是java代码
总结

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

    

总结

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