来一碗剔尖儿 2022-12-07 14:45 采纳率: 100%
浏览 15
已结题

redistemplate模拟获取分布式锁报错

使用redistemplate模拟获取分布式锁,但是报以下错,实际redis连接没有问题,测试是ok的

    @Test
    void testLock(){
        //RedisTask myTask = new RedisTask();
        Thread thread = new Thread(redisTask);
        thread.start();
        for (int i=0;i<2;i++){

        }
    }
package com.practice.redisTest.redisTemplate;

import com.practice.redisTest.redisTemplate.RedisLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

@Component
public class RedisTask implements Runnable{

    @Autowired
    private RedisLock redisLock;
    //private RedisLock redisLock = new RedisLock() ;
    private String lockKey = "myLock";

    @Override
    public void run() {
        // 1.获取锁
        String lockValue = redisLock.getLock(lockKey, 5000, 5);
        if (!StringUtils.hasText(lockValue)) {
            System.out.println(Thread.currentThread().getName() + ",获取锁失败!");
            return;
        }
/*        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/

        // 2.获取锁成功执行业务逻辑
        System.out.println(Thread.currentThread().getName() + ",获取成功,lockValue:" + lockValue);
//        // 3.释放lock锁
        redisLock.unLock(lockKey, lockValue);
    }
}


package com.practice.redisTest.redisTemplate;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@SuppressWarnings(value = {"unchecked", "rawtypes"})
@Component
public class RedisLock {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedisTemplateUtils redisTemplateUtils;

    /**
     * 获取锁
     * @param lockKey key值
     * @param notLockTimeOut 等待时间
     * @param lockTimeOut 锁自动过期时间
     * @return
     */

    public String getLock(String lockKey, int notLockTimeOut, int lockTimeOut) {

        // 定义没有获取锁的超时时间
        Long endTimeOut = System.currentTimeMillis() + notLockTimeOut;
        while (System.currentTimeMillis() < endTimeOut) {
            /*String lockValue = UUID.randomUUID().toString();
            System.out.println(lockValue);*/
            String lockValue = "ceshi";
            //获取成功true
            Boolean flag = redisTemplateUtils.setCacheNxObject(lockKey,lockValue);
            // 如果在多线程情况下谁能够setnx 成功返回true 谁就获取到锁
            System.out.println("======"+flag);
            if (flag) {
                redisTemplateUtils.expire(lockKey, lockTimeOut, TimeUnit.SECONDS);
                return lockValue;
            }
            // 否则情况下 在超时时间内继续循环
        }
        return null;
    }


    /**
     * 释放锁
     * @param lockKey
     * @param lockValue
     * @return
     */
    public Boolean unLock(String lockKey, String lockValue) {
        // 确定是对应的锁 ,才删除
        if (lockValue.equals(redisTemplateUtils.getCacheObject(lockKey))) {
            return redisTemplateUtils.deleteObject(lockKey);
        }
        return false;
    }
}


/**
 * 缓存基本的对象,Integer、String、实体类等
 *
 * @param key      缓存的键值
 * @param value    缓存的值
 * @param timeout  时间
 * @param timeUnit 时间颗粒度
 */
public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
    redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
}

/**
 * setNX
 *
 * @param key      缓存的键值
 * @param value    缓存的值
 */
public <T> Boolean setCacheNxObject(final String key, final T value) {
    return redisTemplate.getConnectionFactory().getConnection()
            .setNX(key.getBytes(Charset.defaultCharset()), value.toString().getBytes(Charset.defaultCharset()));
}

Exception in thread "Thread-2" org.springframework.data.redis.RedisSystemException: Redis exception; nested exception is io.lettuce.core.RedisException: Connection is closed
at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:74)
at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:41)
at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:44)
at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:42)
at org.springframework.data.redis.connection.lettuce.LettuceConnection.convertLettuceAccessException(LettuceConnection.java:272)
at org.springframework.data.redis.connection.lettuce.LettuceConnection.await(LettuceConnection.java:1063)
at org.springframework.data.redis.connection.lettuce.LettuceConnection.lambda$doInvoke$4(LettuceConnection.java:920)
at org.springframework.data.redis.connection.lettuce.LettuceInvoker$Synchronizer.invoke(LettuceInvoker.java:665)
at org.springframework.data.redis.connection.lettuce.LettuceInvoker.just(LettuceInvoker.java:109)
at org.springframework.data.redis.connection.lettuce.LettuceStringCommands.setNX(LettuceStringCommands.java:153)
at org.springframework.data.redis.connection.DefaultedRedisConnection.setNX(DefaultedRedisConnection.java:327)
at com.practice.redisTest.redisTemplate.RedisTemplateUtils.setCacheNxObject(RedisTemplateUtils.java:55)
at com.practice.redisTest.redisTemplate.RedisLock.getLock(RedisLock.java:36)
at com.practice.redisTest.redisTemplate.RedisTask.run(RedisTask.java:19)
at java.lang.Thread.run(Thread.java:748)
Caused by: io.lettuce.core.RedisException: Connection is closed
at io.lettuce.core.protocol.DefaultEndpoint.validateWrite(DefaultEndpoint.java:284)
at io.lettuce.core.protocol.DefaultEndpoint.write(DefaultEndpoint.java:180)
at io.lettuce.core.protocol.CommandExpiryWriter.write(CommandExpiryWriter.java:116)
at io.lettuce.core.RedisChannelHandler.dispatch(RedisChannelHandler.java:191)
at io.lettuce.core.StatefulRedisConnectionImpl.dispatch(StatefulRedisConnectionImpl.java:163)
at io.lettuce.core.AbstractRedisAsyncCommands.dispatch(AbstractRedisAsyncCommands.java:627)
at io.lettuce.core.AbstractRedisAsyncCommands.setnx(AbstractRedisAsyncCommands.java:1581)
at org.springframework.data.redis.connection.lettuce.LettuceInvoker.lambda$just$3(LettuceInvoker.java:109)
... 9 more

Process finished with exit code 0

  • 写回答

0条回答 默认 最新

    报告相同问题?

    问题事件

    • 系统已结题 12月15日
    • 创建了问题 12月7日

    悬赏问题

    • ¥15 android studio导航组件根据导航图配置如何自动生成
    • ¥20 C#上传XML格式数据
    • ¥15 elementui上传结合oss接口断点续传,现在只差停止上传和继续上传,各大精英看下
    • ¥100 单片机hardfaulr
    • ¥20 手机截图相片分辨率降低一半
    • ¥50 求一段sql语句,遇到小难题了,可以50米解决
    • ¥15 速求,对多种商品的购买力优化问题(用遗传算法、枚举法、粒子群算法、模拟退火算法等方法求解)
    • ¥100 速求!商品购买力最优化问题(用遗传算法求解,给出python代码)
    • ¥15 虚拟机检测,可以是封装好的DLL,可付费
    • ¥15 kafka无法正常启动(只启动了一瞬间会然后挂了)