lazyListen()
方法将listening
标志设置为true,然后启动一个Thread来运行SubscriptionTask。调用addMessageListener()
然后使用相同的JedisConnection订阅更多主题。但是在SubscriptionTask启动过程中没有保护,对addMessageListener()
的调用可能在该过程完成之前到达,因此订阅可能完全丢失或者两个线程可能同时写入同一输出流,所以Redis发送了一个损坏的命令。
在取消订阅所有主题后关闭任务时会出现类似问题。在将连接返回池之前,可以在连接上发送新的subscribe命令。如果该连接随后用于非订阅命令,则会发生错误。
通过订阅主题并等待订阅任务完全建立,然后允许进一步连接,并且永远不会取消订阅,可以缓解问题。但即便如此,如果因为抛出异常而关闭任务,它仍然可能发生,因此下次订阅主题时会创建一个新的SubscriptionTask。