我在ZooKeeper类中传递一个监听器匿名对象,经测试发现process方法在每次创建完ZooKeeper对象后都会被调用一次
private final String connectString = "hadoop102:2181,hadoop103:2181,hadoop104:2181";
private final int sessionTimeout = 2000;
private ZooKeeper zkClient;
@Before
public void init() throws IOException {
zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
System.out.println(1);
List<String> children = null;
try {
children = zkClient.getChildren("/", true);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
// for (String child : children) {
// System.out.println(child);
// }
}
});
}
查看源码发现是在ZooKeeper的构造函数里启动了ClientCnxn线程
然后我对在ClientCnxn类中打了几个断点,调试后发现了waitingEvents队列,原来是在初始化ZooKeeper的时候将watcher和event封装为一个pair对象,然后add进waitingEvents队列
我在ClientCnxn类的run方法里发现了调用watcher的具体实现:在这个take方法里会将waitngEvents队列里的封装了watcher、event的队首pair对象赋值给下方的event对象
然后在processEvent方法中调用pair中的event
所以每次初始化ZooKeeper都会执行一次watcher的process方法;而且我自己重写的process抽象方法中还调用了getChildren方法,getChildren方法也会重新将之前的wathcer、event的pair对象重新加入到waitingEvents队列中。