转载链接:https://blog.csdn.net/liyiming2017/article/details/83276706

需求理解
我们先回顾一下例子的需求,此客户端有如下四个需求:

1、它接收如下参数:

ZooKeeper服务的地址
被监控的znode的名称
可执行命令参数
2、它会取得znode上关联的数据,然后执行命令

3、如果znode变化,客户端重新拉取数据,再次执行命令

4、如果znode消失了,客户端杀掉进行的执行命令

如果你已经学习过或者了解过该例子文档的内容,你应该知道该程序做的事情就是接受用户输入的系统命令,然后监控zookeeper的znode,一旦znode存在,或者发生了变化,程序会把znode最新的数据存入文件,然后起一个线程执行用户的命令,同时还会起两个线程输出执行结果及日志。

举例类比
为了帮助理解,这里举个现实的例子--警察抓坏人:

公安成立了一个行动组准备在嫌疑人住所进行抓捕,警方人员安排如下:

  1. 组长A负责总指挥
  2. 警察B负责监控嫌疑人,并与组长A联络
  3. 警察C,D,E,F埋伏在嫌疑人住所前后左右,准备实施抓捕

整个抓捕过程是这样的:

  1. 组长A下达命令安排后,B,C各就各位(对象A做初始化工作)
  2. B开始监控嫌疑人,一旦嫌疑人进入警察布下的埋伏圈,则马上通知组长A(对象B为watcher,嫌疑人为被监听的znode。A注册为B的listener,在B的监听回调中被触发)
  3. 组长A得到通知后,马上命令C、D、E、F执行抓捕。(C,D,E是被A调用干活的线程)

理解了上线的例子,我们继续对程序进行讲解。

Executor和DataMonitor
本例中有两个主要类,职能如下:

Executor,它是程序的入口。负责初始化zookeeper、DataMonitor,把自己注册为DataMonitor的监听者,一旦DataMonitor监听到变化后,会通知它执行业务操作。

他是例子中的组长A,它有几个内部类是前面说的警员C、D、E、F,负责干活。

DataMonitor,他负责监控znode,发现znode变化后,通知listener执行业务逻辑,同时再次监控znode:

他是例子中的警察B,负责监控犯人,并通知A。

通过以上讲解,这两个主要类所负责的工作应该已经可以充分的理解了。接下来我们针对这两个类进入更为详细的讲解。

内部类和接口:
Executor:

StreamWriter。继承Thread,以多线程的形式负责把执行的结果输出。相当于例子中的警察C、D、E、F

DataMonitor:

DataMonitorListener。DataMonitor一旦监控到znode的变化,立即调用自己持有的listener(实现此接口的对象)的exists方法(通知它的监听者)。

继承关系:
Executor:

  • 实现watcher:

    • 监听zookeeper连接的变化,实现process()方法,把事件传递给DataMonitor处理。
  • 实现DataMonitor中定义的接口DataListener:
    • 实现exists()方法,处理znode变化的具体逻辑。
  • 实现runnable类:
    • run()方法中阻塞主线程,让程序转为事件驱动。
public class Executor implements Watcher, Runnable, DataMonitor.DataMonitorListener{}

DataMonitor:

  • 实现watcher:

    • 监听znode变化。实现process()方法,通过zk.exist()方法再次监听,再次设置自己为zookeeper.exist()的回调(实现不断监听,事件驱动)。同时数据返回后,立即进入下面的回调函数处理
  • 实现StatCallback:
    • 这是zookeeper.exist()操作回调对象。实现processResult()方法,调用DataMonitor持有的listener(也就是Excutor)的exists()方法执行逻辑。
public class DataMonitor implements Watcher, StatCallback{} 

引用关系:
Executor:

  • DataMonitor dm;
  • ZooKeeper zk; //ZooKeeper的连接
  • Process child; //真正执行系统命令的子线程,相当于警察C,D,E,F之一。

DataMonitor:

  • ZooKeeper zk; //和Executor是同一个引用。Executor通过构造函数传入
  • DataMonitorListener listener; //executor对象,Executor通过构造函数传入自己

图解

Executor和DataMonitor的关系如下:

两者通过Executor作为主入口,初始化DataMonitor和ZooKeeper对象后,阻塞主线程。转为事件驱动。即通过DataMonitor监控znode上的事件来驱动程序逻辑。

整个流程如下:

  1. Excutor把自己注册为DataMonitor的监听
  2. DataMonitor实现watcher接口,并监听znode
  3. znode变化时,触发DataMonitor的监听回调
  4. 回调中通过ZooKeeper.exist() 再次监听znode
  5. 上一步exist的回调方法中,调用监听自己的Executor,执行业务逻辑6
  6. Executor启新的线程执行命令
  7. Executor启新的线程打印执行命令的输

ZooKeeper java例子解读的更多相关文章

  1. ZooKeeper Java例子(六)

    A Simple Watch Client 为了向你介绍ZooKeeper Java API,我们开发了一个非常简单的监视器客户端.ZooKeeper客户端监视一个ZooKeeper节点的改变并且通过 ...

  2. Java问题解读系列之String相关---String类为什么是final的?

    今天看到一篇名为<Java开发岗位面试题归类汇总>的博客,戳进去看了一下题目,觉得有必要夯实一下基本功了,所以打算边学边以博客的形式归纳总结,每天一道题, 并将该计划称为java问题解读系 ...

  3. 9. 使用ZooKeeper Java API编程

    ZooKeeper是用Java开发的,3.4.6版本的Java API文档可以在http://zookeeper.apache.org/doc/r3.4.6/api/index.html上找到. Ti ...

  4. Zookeeper java api

     Zookeeper java api 主要有以下几个: 方法名称 描述 String create(final String path, byte data[], List acl, CreateM ...

  5. 14.ZooKeeper Java API 使用样例

    转自:http://www.aboutyun.com/thread-7332-1-1.html package com.taobao.taokeeper.research.sample; import ...

  6. ZooKeeper Java Example

    A Simple Watch Client Requirements Program Design The Executor Class The DataMonitor Class Complete ...

  7. Docker Java 例子

    版权所有,未经许可,禁止转载 章节 Docker 介绍 Docker 和虚拟机的区别 Docker 安装 Docker Hub Docker 镜像(image) Docker 容器(container ...

  8. zookeeper java调用及权限控制

    import java.io.IOException; import java.security.NoSuchAlgorithmException; import java.util.ArrayLis ...

  9. zookeeper - java操作

    ZKUtils.java package test; import java.io.IOException; import java.util.concurrent.CountDownLatch; i ...

随机推荐

  1. 四、redis学习(案例)

    效果如下 注意:必须要开启redis服务器端 数据库 CREATE DATABASE heima; -- 创建数据库 USE heima; -- 使用数据库 CREATE TABLE province ...

  2. vue组件之子组件和父组件

    在看官网和学习的过程中,有些不明确子组件和父组件的定义,为了方便后期学习和理解去网站上搜索了一下相关的解释 1.使用的地方是父组件,定义的地方是子组件,虽然他们是同一个组件 2.Vue.compone ...

  3. linux命令详解——vim

    显示行号:命令模式下set nu 定位到指定行: 命令模式下,:n   比如想到第2行,:2 编辑模式下,ngg  比如想到第5行 5gg(或者5G) 打开文件定位到指定行   vim  +n  te ...

  4. python的内建函数chr,ord

    python的内建函数chr,ord,unichr chr()函数用一个范围在range(256)内的(就是0-255)整数作参数,返回一个对应的字符.unichr()跟它一样,只不过返回的是Unic ...

  5. ibatis与mybatis的区别

    一.最主要的区别就是mybatis简化了编码的过程,不需要去写dao的实现类,直接写一个dao的借口,再写一个xml配置文件,整个mybatis就配置好了,也就是数据库就连接好了,然后再service ...

  6. 第二章 Vue快速入门-- 19 v-if和v-show的使用和特点

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  7. Kubernetes 编排神器之 Helm

    什么是Kubernetes Helm?为什么要使用Helm? 前言 编写一堆Kubernetes配置文件是一件很麻烦的事情.对于一些容器,我们可能需要10多个yaml文件.维护它们是一个问题,而且在不 ...

  8. HDU4456-Crowd (坐标旋转处理+hash处理+二维树状数组)

    题意: 给出一个矩阵,初始每个位置上的值都为0,然后有两种操作 一种是更改某个位置上的值 另一种是求某个位置附近曼哈顿距离不大于K的所有位置的值的总和 技巧: 坐标旋转,使得操作之后菱形变成方方正正的 ...

  9. python类内置方法的再学习

    对于__setitem__和__getitem__方法:其入参看来是固定的(__getitem__(self, item),__setitem__(self, key, value)),我们并不需要重 ...

  10. 2017 网易游戏互娱游戏研发4.21(offer)

    网易游戏互娱(offer) 去年这个时候就参加过网易游戏的实习生招聘,到今年总共收到了4次拒信.不过这次运气好,终于get了最想要的offer.去年实习生互娱笔试挂,秋招笔试挂,今年春招互娱投了连笔试 ...