Reids客户端Jedis的JedisSentinelPool关闭问题

  JedisSentinelPool使用一组MasterListener线程做主从复制的主服务器选举工作。其父类Pool的close, destory方法用来关闭正真的redis客户端连接池的对象。在JedisSentinelPool对象中重写了destory方法内容是在关闭选举线程之后,调用了父类destory方法;但是没有重写close方法,因而调用close方法不能关闭的掉MasterLinstener线程。Pool的另一个子类JedisPool则没有对close,destory方法做任何变动。

 

 JedisSentinelPool,JedisPool以及Pool之间的关系如下类图:

 Reids客户端Jedis的JedisSentinelPool关闭问题_第1张图片


 查看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是数字),这样很不方便排错。!!!所以启动线程起个好名字真的非常必要,这将对排错,诊断,系统监控有莫大的帮助。

你可能感兴趣的:(数据库,java)