springboot2+redis 订阅发布,解决接收消息累计线程到内存溢出,使用自定义线程池接收消息

pom 添加redis

java 复制代码
		<!-- redis 缓存操作 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>

发布消息

java 复制代码
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

/**
 * @author zpy
 * @date 2023/8/9 13:48
 */
@Slf4j
@Component
public class RedisMessageUtils {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 向通道发布消息
      * topic 通道名称
     */
    public void sendMessage(String topic, Object message) {
        if (!StringUtils.hasText(topic)) {
            return;
        }
        try {
            stringRedisTemplate.convertAndSend(topic, message);
            log.info("发送消息成功,topic:{},message:{}", topic, message);
        } catch (Exception e) {
            log.info("发送消息失败,topic:{},message:{}", topic, message);
            e.printStackTrace();
        }
    }

}

接收消息

java 复制代码
    /**
     * Redis消息监听器容器
     * 这个容器加载了RedisConnectionFactory和消息监听器
     * 可添加多个不同话题的redis监听器,需要将消息监听器和消息频道绑定,
     * 通过反射调用消息订阅处理器的相关方法进行业务处理
     *
     * @param  redisConnectionFactory   	连接工厂
     * @param  listener                 	Redis消息监听器
     * @param  MessageListenerAdapter   	Redis消息监听适配器
     * @return RedisMessageListenerContainer    消息监听容器
     */
    @Bean
    @SuppressWarnings("all")
    public RedisMessageListenerContainer container(RedisMessageListener listener) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactorySlave());
        // 所有的订阅消息,都需要在这里进行注册绑定
        // new PatternTopic(TOPIC_NAME1) 表示发布信息的频道
        // 可以添加多个频道以及配置不同的频道
        container.addMessageListener(listener, new PatternTopic("消息频道名称"));
        //container.addMessageListener(adapter, new PatternTopic(SystemConstants.TOPIC_NAME2));
        container.setTaskExecutor(springSessionRedisTaskExecutor());

        /**
         * 设置序列化对象
         * 特别注意:1. 发布的时候和订阅方都需要设置序列化
         *         2. 设置序列化对象必须放在 {加入消息监听器} 这步后面,不然接收器接收不到消息
         */
		/*Jackson2JsonRedisSerializer seria = new Jackson2JsonRedisSerializer(Object.class);
		ObjectMapper objectMapper = new ObjectMapper();
		objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
		objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
		seria.setObjectMapper(objectMapper);
		container.setTopicSerializer(seria);*/
        return container;
    }

/** 自定义接收消息的线程池
*/
    @Bean
    public ThreadPoolTaskExecutor springSessionRedisTaskExecutor() {
        ThreadPoolTaskExecutor springSessionRedisTaskExecutor = new ThreadPoolTaskExecutor();
        springSessionRedisTaskExecutor.setCorePoolSize(8);
        springSessionRedisTaskExecutor.setMaxPoolSize(15);
        springSessionRedisTaskExecutor.setKeepAliveSeconds(10);
        springSessionRedisTaskExecutor.setQueueCapacity(1000);
        springSessionRedisTaskExecutor.setThreadNamePrefix("redis-");
        return springSessionRedisTaskExecutor;
    }

测试

java 复制代码
@Scheduled(cron = "0/10 * * * * *")
	private void init(){

		for(int i=0;i<50;i++){
			//处理请求
			redisMessageUtils.sendMessage("接收频道名称", UUID.randomUUID().toString());
		}
	}
相关推荐
xqqxqxxq几秒前
Java 集合框架之线性表(List)实现技术笔记
java·笔记·python
L0CK9 分钟前
RESTful风格解析
java
程序员小假18 分钟前
我们来说说 ThreadLocal 的原理,使用场景及内存泄漏问题
java·后端
何中应20 分钟前
LinkedHashMap使用
java·后端·缓存
tryxr28 分钟前
Java 多线程标志位的使用
java·开发语言·volatile·内存可见性·标志位
talenteddriver33 分钟前
java: Java8以后hashmap扩容后根据高位确定元素新位置
java·算法·哈希算法
云泽80836 分钟前
STL容器性能探秘:stack、queue、deque的实现与CPU缓存命中率优化
java·c++·缓存
无盐海36 分钟前
Redis 哨兵模式
数据库·redis·缓存
yyy(十一月限定版)42 分钟前
c语言——栈和队列
java·开发语言·数据结构
本地运行没问题1 小时前
基于Java注解、反射与动态代理:打造简易ORM框架
java