解决Redis java.lang.IllegalStateException: Cannot connect, Event executor group is terminated

本文探讨了在Spring Boot应用中使用ZSet实现的消息队列遇到的Cannotconnect错误,通过实现DisposableBean接口和@PreDestroy注解处理程序关闭时的连接问题,确保线程安全并避免资源泄露。

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

问题产生背景

  • 写了个基于zset的消息队列(因为公司redis还是3.2.9的,没法用stream),然后有个线程一直轮询取数据。
    在这里插入图片描述

  • 然后我关闭应用时可能会报Cannot connect, Event executor group is terminated,如下所示。
    在这里插入图片描述

 Exception in thread "loop-redis-queue" java.lang.IllegalStateException: Cannot connect, Event executor group is terminated.
	at io.lettuce.core.AbstractRedisClient.initializeChannelAsync(AbstractRedisClient.java:283)
	at io.lettuce.core.RedisClient.connectStatefulAsync(RedisClient.java:314)
	at io.lettuce.core.RedisClient.connectStandaloneAsync(RedisClient.java:271)
	at io.lettuce.core.RedisClient.connect(RedisClient.java:204)
	at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.lambda$getConnection$1(StandaloneConnectionProvider.java:113)
	at java.util.Optional.orElseGet(Optional.java:267)
	at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.getConnection(StandaloneConnectionProvider.java:113)
	at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getNativeConnection(LettuceConnectionFactory.java:1110)
	at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getConnection(LettuceConnectionFactory.java:1091)
	at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getSharedConnection(LettuceConnectionFactory.java:872)
	at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getConnection(LettuceConnectionFactory.java:347)
	at org.springframework.data.redis.core.RedisConnectionUtils.doGetConnection(RedisConnectionUtils.java:134)
	at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:97)
	at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:84)
	at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:212)
	at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:185)
	at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:96)
	at org.springframework.data.redis.core.DefaultZSetOperations.rangeByScore(DefaultZSetOperations.java:197)
	at com.springboot.sample.redis.DelayingQueueService.pop(DelayingQueueService.java:88)
	at com.springboot.sample.redis.DelayingQueueService$1.run(DelayingQueueService.java:124)

问题分析

解决方案

  • Spring有对关闭程序,销毁bean回调的扩展,例如实现DisposableBean接口或者 使用@PreDestroy注解。@PreDestroy注解被调用早于DisposableBean接口,我用的@PreDestroy。
  • 增加销毁标记
    /** 是否销毁标记 volatile 保证可见性 **/
    private volatile boolean destroyFlag = false;
  • 修改标记
    @PreDestroy
    public void destroy() throws Exception {
        System.out.println("应用程序已关闭");
        this.destroyFlag = true;
    }
  • 然后在轮询的地方加入判断
...省略...
while (!Thread.interrupted() && !destroyFlag) {
...省略...
  • 我去掉线程睡眠,测试了大约5次,没有再报异常。结果如下gif图。
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值