SpringBoot整合redisTemplate时,多线程无法操作

本文分析了一名开发者在配置Spring Boot与RedisTemplate时遇到的问题,发现一个RedisTemplate实例可能导致线程池资源竞争,解决办法是使用单例模式并合理管理Redis连接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.我配置了一个redisTemplate
@Configuration
public class RedisConfig {

    /**
     * 生成操作Redis的bean--RedisTemplate,并将其注入到Spring容器中
     *
     * @param factory redis连接工厂
     * @return 配置好的RedisTemplate
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        //为了自己开发方便,一般直接使用<String,Object>
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        //自定义序列化器
        Jackson2JsonRedisSerializer<Object> objectJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        //Json序列化配置使用ObjectMapper进行转义
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        objectJackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        //String的序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        //key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        //hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        //value序列化方式采用jackson
        template.setValueSerializer(stringRedisSerializer);
        //hash的value序列化方式采用jackson
        template.setHashValueSerializer(stringRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}
2.定义了一个Redis工具类注入到了Spring容器中
@Component
public class RedisUtil {
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    public String get(String from,String to,String key){
        ValueOperations<String, Object> ops = redisTemplate.opsForValue();
        try {
            return (String) ops.get(key + ":" + from + ":" + to);
        }
        catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    public void set(String from,String to,String key,String obj){
        ValueOperations<String, Object> ops = redisTemplate.opsForValue();
        try {
            redisTemplate.multi();
            ops.set(key + ":" + from + ":" + to,obj);
            redisTemplate.exec();
        }
        catch (Exception e){
            redisTemplate.discard();
        }
    }
}
3.开了一个线程来执行方法
@Component
@Slf4j
public class AsyncHandShakeTask {
    @Autowired
    private HandShakeService handShakeService;
    @Autowired
    private RedisUtil redisUtil;

    @Async
    public Future<String> doHandShake(String from,String to){
        long start = System.currentTimeMillis();
        log.info("***************开始加锁***************");
        redisUtil.set(from,to,"lock","1");
        log.info("***************开始执行握手***************");
        handShakeService.doHandShake();
        log.info("***************执行握手结束***************");
        log.info("***************开始解锁***************");
        redisUtil.set(from,to,"lock","0");
        long end = System.currentTimeMillis();
        log.info("*****任务全部完成,总耗时:" + (end - start) + "毫秒*****");
        return new AsyncResult<>("任务全部完成,总耗时:" + (end - start) + "毫秒");
    }

    @Async
    public void testRedis(){
        System.out.println("开始设置");
        com.platform.security.util.RedisUtil.set("1","2","test","v");
        System.out.println("设置完成");
    }
}

然后开启线程执行该方法时,就是执行不了,也不是报错,就是执行到

 redisUtil.set(from,to,"lock","1");

这句之后,线程自动就退出了。该句也能执行成功。
然后我就十分奇怪,之后,在网上找相关资料时发现一个redisTemplate实例只能占有一个jedis链接。所以感觉可能是这个原因,然后就自己直接使用jedis创建一个连接进行了操作,发现可行。
如果有大佬遇到过同样的情况请告知一二。

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值