[Zookeeper学习笔记之三]Zookeeper实例创建和会话建立的异步特性
编程技术  /  houtizong 发布于 3年前   61
为了说明问题,看个简单的代码,
import org.apache.zookeeper.*; import java.io.IOException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ThreadLocalRandom; public class ZKApplication implements Watcher { private static final int SESSION_TIMEOUT = 3000; private volatile static boolean shutdown; private ZooKeeper zk; private CountDownLatch connectedSignal = new CountDownLatch(1); public void connect(String hosts) throws IOException, InterruptedException { try { System.out.println("Start to create the Zookeeper instance"); zk = new ZooKeeper(hosts, SESSION_TIMEOUT, this); new Thread(new Runnable() { int count = 0; @Override public void run() { while (count++ <= 1000) { System.out.println(zk.getState()); try { Thread.currentThread().sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } catch(IOException e) { e.printStackTrace(); throw e; } connectedSignal.await(); //Wait for the SyncConnected event occurs and process has been called, which will stop the waiting here. } } @Override public void process(WatchedEvent event) { // Watcher interface if (event.getState() == Event.KeeperState.SyncConnected) { connectedSignal.countDown(); //connectedSignal.await() will no longer wait } } public void create(String groupName) throws KeeperException, InterruptedException { String path = "/" + groupName; String createdPath = zk.create(path, null/*data*/, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); //The znode will be deleted upon the session is closed. System.out.println("Created " + createdPath); } public void close() throws InterruptedException { zk.close(); } public static void main(String[] args) throws Exception { final ZKApplication createGroup = new ZKApplication(); String groupName = "zoo" + ThreadLocalRandom.current().nextInt(); createGroup.connect(Host.HOST); createGroup.create(groupName); createGroup.close(); } }
上面的代码在Zookeeper没有启动的情况下,控制台输出1000次CONNECTING,也不退出,原因是已经发生了死锁问题。 引发死锁问题的是同步闭锁connectedSignal的使用,代码中的含义是客户端在connect方法中发起链接,然后connect一直等待直到 Watcher的process被回调将闭锁计数置零,通常这个没有问题,可是当Zookeeper压根没有启动的时候,这个代码会陷入死锁:
了解了Zookeeper对象实例化和会话建立的异步性,一方面可以了解Zookeeper的设计策略,另一方面,也可以避免一些代码和同步策略导致的陷阱,比如代码中那样。
虽然代码中主线程已经阻塞于connect方法,可是当Zookeeper服务器启动后,Client会建立连接,然后回调Watcher的process方法,此时就会解锁,从这个角度上来说,这里的死锁应该不叫事,应该启动这个程序目的就是要有Zookeeper在运行才好,如果Zookeeper之后断了,connectionsignal这个闭锁已经不再起作用。
请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!
技术博客集 - 网站简介:
前后端技术:
后端基于Hyperf2.1框架开发,前端使用Bootstrap可视化布局系统生成
网站主要作用:
1.编程技术分享及讨论交流,内置聊天系统;
2.测试交流框架问题,比如:Hyperf、Laravel、TP、beego;
3.本站数据是基于大数据采集等爬虫技术为基础助力分享知识,如有侵权请发邮件到站长邮箱,站长会尽快处理;
4.站长邮箱:[email protected];
文章归档
文章标签
友情链接