zookeeper应用案例——分布式锁

来源:互联网 发布:win32api c语言 编辑:程序博客网 时间:2024/05/16 00:29

需要的jar包:

zookeeper-3.4.5\zookeeper-3.4.5.jar
zookeeper-3.4.5\lib\所有jar包



DemoServer.java:

public class DemoServer {private static ZooKeeper zkCli = null;static boolean haveLock = false;private final static String groupNode = "/locks";private static String myNodePath;private static String hostname;public static void waitUntilConnected(ZooKeeper testZooKeeper, CountDownLatch testLatch) {        if(testZooKeeper.getState() == States.CONNECTING) {            try {                testLatch.await();            } catch (InterruptedException err) {                System.out.println("Latch exception");            }        }    } static class ConnectedWatcher implements Watcher {        private CountDownLatch connectedLatch;        ConnectedWatcher(CountDownLatch connectedLatch) {            this.connectedLatch = connectedLatch;  /* CountDownLatch实例初始化时设为1即可 */        }        @Override        public void process(WatchedEvent event) {            if (event.getState() == KeeperState.SyncConnected) {                connectedLatch.countDown(); /* ZK连接成功时,计数器由1减为0 */            }            if(event.getType()!=EventType.NodeChildrenChanged) return;try{// 用zk客户端去获取锁权限haveLock = gainLock();if (haveLock) {System.out.println(hostname + " gained the lock....");// 拿到锁之后,调用业务处理方法进行业务处理doSomeThing();// 释放锁releaseLock();// 重新创建锁节点并注册监听registerLock();}}catch(Exception e){e.printStackTrace();}        }    } /** * 获取锁,然后去访问共享资源进行业务处理 */public void gainLockAndDoSomething() throws Exception {CountDownLatch sampleLatch = new CountDownLatch(1);Watcher sampleWatcher = new ConnectedWatcher (sampleLatch);// 构造一个zookeeper的客户端zkCli = new ZooKeeper("192.168.77.70:2181", 2000, sampleWatcher);/* 只有当zkCli链接成功(状态为 SyncConnected)时,此函数调用才结束 */ waitUntilConnected(zkCli, sampleLatch);        /*接下来就可以继续zkCli访问了,避免因为zkCli未连接成功时的访问出错 */// 用zk客户端向"/locks"下注册一把自己的锁节点registerLock();// 让线程稍微休眠一下Thread.sleep((long) (Math.random() * 500 + 500));// 用zk客户端去获取锁权限haveLock = gainLock();if (haveLock) {System.out.println(hostname + " gained the lock....");// 拿到锁之后,调用业务处理方法进行业务处理doSomeThing();// 释放锁releaseLock();// 重新创建锁节点并注册监听registerLock();}}/** * 注册锁节点信息以用于竞争锁权限 */public static void registerLock() throws KeeperException, InterruptedException {// 向zookeeper中注册一个自己的锁节点,并把该锁节点路径记录在myNodePath变量中myNodePath = zkCli.create(groupNode + "/lock", null, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);}/** * 获取锁权限 逻辑是:自己创建的锁节点如果是所有锁节点中最小的一个,则获得锁权限 */public static boolean gainLock() throws KeeperException, InterruptedException {List<String> children = zkCli.getChildren(groupNode, true);// 如果子节点列表就只有1个元素,那么说明,当前就只有我这一个节点在线,我就可以直接获得所权限if (children.size() == 1)return true;Collections.sort(children);// myNodePath : /locks/lock0000001if (children.get(0).equals(myNodePath.substring(groupNode.length() + 1))) {return true;} else {return false;}}/** * 模拟访问共享资源并进行业务处理的方法 */public static void doSomeThing() throws InterruptedException {System.out.println("begin working .......");Thread.sleep((long)(Math.random()*1000+500));System.out.println("work has complished.....");}/** * 释放所权限 * 逻辑:删除掉自己的锁节点 */public static void releaseLock() throws InterruptedException, KeeperException {zkCli.delete(myNodePath, -1);}/** * 程序的入口 */public static void main(String[] args) throws Exception {hostname = args[0];// 去获取锁并且进行业务处理DemoServer demoServer = new DemoServer();demoServer.gainLockAndDoSomething();// 主线程休眠Thread.sleep(Long.MAX_VALUE);}}


结果: