redis默认连接池的这个坑,你真的知道吗?
后来仔细看了一下,有一行日志引起了我的注意,如下图所示:
RedisMessageListenerContainer类无法取消对订阅的订阅。
我勉为其难的用自己的工地英语尝试着翻译了一波,大概意思是说:这是为Redis消息监听器提供异步行为的容器。处理低层次的倾听细节,转换和消息发送。与低级别的Redis(每个订阅一个连接)相反,容器只使用一个连接。
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerCutVideoAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerCutVideoAdapter, new PatternTopic(channelName));
return container;
}
container.setConnectionFactory(connectionFactory);
这个ConnectionFactory看上去像个连接工厂,会不会里面有点玄机呢?
点进去看看,发现果真是这样。
这个RedisConnectionFactory是用@Nllable标注的,代表该对象可以为空。类里有两个方法为createDefaultTaskExecutor(),和afterPropertiesSet();
afterPropertiesSet()大家应该都不陌生,这个方法将在所有的属性被初始化后调用(对于InitializingBean的细节这里不再赘述)。
public void afterPropertiesSet() {
if (taskExecutor == null) {
manageExecutor = true;
taskExecutor = createDefaultTaskExecutor();
}
if (subscriptionExecutor == null) {
subscriptionExecutor = taskExecutor;
}
initialized = true;
}
而这个“线程池”处理任务时每次都创建新的线程。所以你会发现很多个redisMessageListenerContailner-X线程。
最后的题外话:
Spring 已经实现的异常线程池:
1. SimpleAsyncTaskExecutor:不是真的线程池,这个类不重用线程,每次调用都会创建一个新的线程。
2. SyncTaskExecutor:这个类没有实现异步调用,只是一个同步操作。只适用于不需要多线程的地方
3.ConcurrentTaskExecutor:Executor的适配类,不推荐使用。如果ThreadPoolTaskExecutor不满足要求时,才用考虑使用这个类
4.SimpleThreadPoolTaskExecutor:是Quartz的SimpleThreadPool的类。线程池同时被quartz和非quartz使用,才需要使用此类
5. ThreadPoolTaskExecutor :最常使用,推荐。其实质是对java.util.concurrent.ThreadPoolExecutor的包装