JedisSentinelPool使用一组MasterListener线程做主从复制的主服务器选举工作。其父类Pool的close, destory方法用来关闭正真的redis客户端连接池的对象。在JedisSentinelPool对象中重写了destory方法内容是在关闭选举线程之后,调用了父类destory方法;但是没有重写close方法,因而调用close方法不能关闭的掉MasterLinstener线程。Pool的另一个子类JedisPool则没有对close,destory方法做任何变动。
JedisSentinelPool,JedisPool以及Pool之间的关系如下类图:
查看Pool中close和destory的源码:
@Override public void close() { closeInternalPool(); }
public void destroy() { closeInternalPool(); }
close方法实现自java.io.Closeable接口,Closeable是可以关闭的数据源或目标。调用 close 方法可释放对象保存的资源(如打开文件)从这一点看是没有问题的,如果是JDK1.7+的话,那更好了该接口继承了AutoCloseable接口。对于JedisPool而言调用close方法和调用destory效果是一样的,但JedisSentinelPool就不同了,创建JedisSentinelPool是启动了MasterLinstener线程,所以得调用destory方法来完成JedisSentinelPool所持有的资源释放,线程关闭。
JedisSentinelPool的destory方法:
public void destroy() { for (MasterListener m : masterListeners) { m.shutdown(); } super.destroy(); }
结论:如果要关闭的仅仅是Pool(Reids客户端连接池)则调用close,而要关闭主从复制中的主机检测即彻底关闭JedisSentinelPool则要调用destory方法。
意外想当然的调用close方法,并没能关闭MasterLinstener线程,并且MasterLinstener线程没有起个好名字,排查是看到的名字叫Thread-xx (xx是数字),这样很不方便排错。!!!所以启动线程起个好名字真的非常必要,这将对排错,诊断,系统监控有莫大的帮助。