class LockThread implements Runnable {
private DistributedLock lock; public LockThread(int threadId,CountDownLatch latch) throws Exception {
this.lock = new DistributedLock(threadId,latch);
} @Override
public void run() {
//每一个线程对象启动后都应该创建一个临时的节点信息
try {
this.lock.handle();//进行具体的操作处理
} catch (Exception e) {
e.printStackTrace();
}
}
} public class TestDistributedLock { public static void main(String[] args) throws Exception {
CountDownLatch latch = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
new Thread(new LockThread(i,latch)).start();;
}
//Thread.sleep(Long.MAX_VALUE);//为了保证可以观察到所有的临时节点信息,保证此处先不进行关闭
latch.await();
System.out.println("************* 所有的线程对象操作完毕 *************");
}
public class DistributedLock {//建立一个描述分布式锁的程序处理类
public static final String CONNECTION_RUL = "192.168.12.121:2181,192.168.12.122:2181"; public static final int SESSION_TIMEOUT = 2000;//设置连接超时时间 public static final String AUTH_INFO = "zkuser:mldnjava";//进行连接的授权信息 public static final String GROUPNODE = "/mldn-lock";//根节点 public static final String SUNBODE = GROUPNODE + "/lockthread-";//子节点 private CountDownLatch latch = null; //本操作的主要目的是为了在取得zookeeper连接之后才能进行后续的处理
private CountDownLatch connectLatch = new CountDownLatch(1); private ZooKeeper zkClient = null; //建立Zookeeper程序控制类 private String selfPath; //保存每次创建的临时节点信息 private String waitPath; //保存下一个要进行处理的节点 private int threadId = 0; /** 进行一些初始化操作使用
*
* @param threadId 随意给定一个编号信息 * @param latch 进行线程同步处理
* @throws Exception */
public DistributedLock(int threadId, CountDownLatch latch) throws Exception {
this.threadId = threadId;//保存每一个线程对象自己的ID信息
this.latch = latch;
this.connectionZookeeper();//进行节点的连接
} public void handle() throws Exception {//具体业务处理
this.createSubNode();//创建临时节点操作
} public void handleSuccess() throws Exception {//表示取得锁之后进行的处理
if (this.zkClient.exists(this.selfPath, false) == null) {
return;//如果当前节点不存在
}
this.handleCallback();//执行具体的业务操作
//如果某一个节点操作完毕了,那么应该立即删除掉该节点,否则获得的最小节点永远都是该节点
this.zkClient.delete(selfPath, -1);
this.releaseZookeeper();//释放连接
this.latch.countDown();//进行减减的操作
} public void handleCallback() throws Exception {//取得分布式锁之后的目的是要进行具体的操作
Thread.sleep(200);//实现一个延迟处理
System.out
.println("****** Thread-" + this.threadId + "获得操作权,进行具体的业务操作");
} public boolean checkMinPath() throws Exception {//进行最小节点的判断
List<String> childen = this.zkClient.getChildren(GROUPNODE, false);//取得所有的节点信息
Collections.sort(childen); //进行所有节点的排序,这样最小的节点就拍到最上面
int index = childen
.indexOf(this.selfPath.substring(GROUPNODE.length() + 1));
switch (index) {
case 0: {
return true; //已经确定好当前的节点为最小节点
}
case -1: {
return false; //该节点可能已经消失了
}
default: {//表示该节点不属于最小节点,那么应该向后继续排查
this.waitPath = GROUPNODE + "/" + childen.get(index - 1);//获得下一个节点
try {
this.zkClient.getData(waitPath, true, new Stat());//取得下一个节点的数据
return false; //本节点不是当前的操作的最小节点
} catch (Exception e) {//如果出现了异常,则表示该节点不存在
if (this.zkClient.exists(waitPath, false) == null) {
return this.checkMinPath();//继续向后检测
} else {
throw e;
}
}
}
}
} public void createSubNode() throws Exception {//每一个线程对象的启动都要求创建一个节点信息
this.zkClient.create(SUNBODE, ("Thread-" + this.threadId).getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println("【Thread-" + this.threadId + "、创建新的临时节点】"
+ this.selfPath);
//当节点创建完成之后就需要进行最小节点的检测
if (this.checkMinPath()) {//如果当前的节点为整个项目的最小节点
this.handleSuccess();//进行锁后的具体操作
}
} public void connectionZookeeper() throws Exception {//连接zookeeper服务
this.zkClient = new ZooKeeper(CONNECTION_RUL, SESSION_TIMEOUT,
new Watcher() { @Override
public void process(WatchedEvent event) {
if (event.getType() == EventType.None) {//第一次连接zookeeper的时候会出现none
DistributedLock.this.connectLatch.countDown();//表示已经连接成功
} else { //要处理删除节点操作,并且要确定下一个节点是已经准备出来的节点信息
if (event.getType() == EventType.NodeDeleted
&& event.getPath().equals(
DistributedLock.this.waitPath)) {
try {
if (DistributedLock.this.checkMinPath()) {//如果当前的节点为整个项目的最小节点
DistributedLock.this.handleSuccess();//进行锁后的具体操作
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
});
this.zkClient.addAuthInfo("digest", AUTH_INFO.getBytes());//进行授权认证
if (this.zkClient.exists(GROUPNODE, false) == null) {
this.zkClient.create(GROUPNODE, "LOCKDEMO".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
this.connectLatch.await();//等待连接后才执行后续的功能
} public void releaseZookeeper() {//进行zookeeper的连接释放
if (this.zkClient != null) {
try {
this.zkClient.close();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

ZooKeeper连接并创建节点以及实现分布式锁操作节点排序输出最小节点Demo的更多相关文章

  1. zookeeper应用:屏障、队列、分布式锁

    zookeeper工具类: 获取连接实例:创建节点:获取子节点:设置节点数据:获取节点数据:访问控制等. package org.windwant.zookeeper; import org.apac ...

  2. ZooKeeper实践方案:(7) 分布式锁

    1.基本介绍 分布式锁是控制分布式系统之间同步訪问共享资源的一种方式,须要相互排斥来防止彼此干扰来保证一致性. 利用Zookeeper的强一致性能够完毕锁服务.Zookeeper的官方文档是列举了两种 ...

  3. zookeeper 实现分布式锁zookeeper 使用 Curator 示例监听、分布式锁

    下载地址: http://download.csdn.net/download/ttyyadd/10239642

  4. 在非SQL客户端使用命令行方式定期连接SQL Server 服务器并模拟用户查询操作,同时输出信息内容

    一个很长的标题,实现的功能就是尽量使用非人力的方式模拟人去做一件事情,为了便于记录,将他们输出成文件方便查阅. 图形界面方式,使用微软自己的ConnMaker.exe,或者Microsoft 数据连接 ...

  5. 整理分布式锁:业务场景&分布式锁家族&实现原理

    1.引入业务场景 业务场景一出现: 因为小T刚接手项目,正在吭哧吭哧对熟悉着代码.部署架构.在看代码过程中发现,下单这块代码可能会出现问题,这可是分布式部署的,如果多个用户同时购买同一个商品,就可能导 ...

  6. zookeeper分布式锁实现

    1.定义分布式锁接口 package com.ljq.lock; import java.util.concurrent.TimeUnit; public interface DistributedL ...

  7. 分布式锁2 Java非常用技术方案探讨之ZooKeeper

    前言:       由于在平时的工作中,线上服务器是分布式多台部署的,经常会面临解决分布式场景下数据一致性的问题,那么就要利用分布式锁来解决这些问题.以自己结合实际工作中的一些经验和网上看到的一些资料 ...

  8. 跟着大神学zookeeper分布式锁实现-----来自Ruthless

    前几天分享了@Ruthless大神的Redis锁,发现和大家都学习了很多东西.因为分布式锁里面,最好的实现是zookeeper的分布式锁.所以在这里把实现方式和大家分享一下. zookeeper分布式 ...

  9. zookeeper分布式锁

    摘要:分享牛原创,zookeeper使用,zookeeper锁在实际项目开发中还是很常用的,在这里我们介绍一下zookeeper分布式锁的使用,以及我们如何zookeeper分布式锁的原理.zooke ...

随机推荐

  1. RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.3版本全新发布

    1.RDIFramework.NET框架介绍 RDIFramework.NET,基于.NET的快速信息化系统开发.整合框架,为企业或个人快速开发系统提供了强大的支持,开发人员不需要开发系统的基础功能和 ...

  2. Spring Cloud Alibaba基础教程:使用Sentinel实现接口限流

    最近管点闲事浪费了不少时间,感谢网友libinwalan的留言提醒.及时纠正路线,继续跟大家一起学习Spring Cloud Alibaba. Nacos作为注册中心和配置中心的基础教程,到这里先告一 ...

  3. MySQL 笔记整理(10) --MySQL为什么有时会选错索引?

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 10) --MySQL为什么有时会选错索引? MySQL中的一张表上可以 ...

  4. 一个tomcat设置多个端口,多个端口对应多个应用

    修改tomcat/conf目录里面server.xml文件 例如下面这样新增一个8090端口,设置下appBase目录,这样就可以用一个tomcat监听多个端口,每个端口都可以放应用了.我这样新增下面 ...

  5. 对于jQuery的了解

    1.了解jQuery与JavaScript的区别 css --外貌特征Html --躯干,骨架js --运动神经 jQuery就是对JavaScript的一个拓展,封装,就是让JavaScript更好 ...

  6. Java笔记(day11)

    异常:是在运行时期发生的不正常情况. 异常类:在java中用类的形式对不正常情况进行了描述和封装对象,描述不正常的情况的类. 异常就是java通过面向对象的思想将问题封装成了对象.用异常类对其进行描述 ...

  7. MySQL InnoDB 存储引擎探秘

    在MySQL中InnoDB属于存储引擎层,并以插件的形式集成在数据库中.从MySQL5.5.8开始,InnoDB成为其默认的存储引擎.InnoDB存储引擎支持事务.其设计目标主要是面向OLTP的应用, ...

  8. Java 单例(Singleton)模式

    一.什么是单例模式: 单例模式是一种确保了一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.被实例化的类称为单例类. 二.单例模式的特点: 单例类只有一个实例. 单例类必须自行创建自己唯一的 ...

  9. 三位数流水码的生成(000·····009··00A····00Z····ZZZ)

    //规格代码的生成 private String getCode (String code) { char[] chars=code.toCharArray(); if (chars[2]==57){ ...

  10. HTML中的Hack条件注释语句

    IE 条件注释判断语句是 IE 特有的功能,通过 HTML 注释中的条件语句能让不同的 IE 版本识别注释中的内容 自IE10起,标准模式不再支持条件注释 条件注释语句中可以是HTML.CSS也可以是 ...