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. Cortex-M 实现互斥操作的三种方法

    注:本文仅针对Cortex-M3/4 系列进行讲述. 在传统的ARM处理器架构中,常使用SWP指令来实现锁的读/写原子操作,但从ARM v6开始,读/写访问在独立的两条总线上进行,SWP指令已无法在此 ...

  2. 微信公众号开发C#系列-1、微信公众平台注册

    微信公众号简介 微信公众号分为服务号.订阅号.企业号,订阅号可以个人申请,服务号和企业号要有企业资质才可以. 我们所说的微信公众号开发主要指的是公众号的账号类型,公众号的账号类型分为订阅号.服务号.企 ...

  3. 使用cookie来做身份认证

    文章是msdn的官方文档,链接在这里.其实也有中文的文档,这里还是想做一个记录. 文章有asp.net core 2.x 和1.x 版本,我这里就忽略1.x了. 下面先说几点额外的东西有助于理解. A ...

  4. Web部分

    说出Servlet的生命周期,并说出Servlet和GCI的区别. Web容器加载Servlet并将其实例化后,Servlet生命周期开始,容器运行其init方法进行Servlet的初始化,请求到达时 ...

  5. Springboot整合activemq

    今天呢心血来潮,也有很多以前的学弟问到我关于消息队列的一些问题,有个刚入门,有的有问题都来问我,那么今天来说说如何快速入门mq. 一.首先说下什么是消息队列? 1.消息队列是在消息的传输过程中保存消息 ...

  6. zookeeper安装以及遇到的一些坑

    最近项目中用到了storm,然后storm中用到了zookeeper,然后今天抽空整理一下zookeeper的安装使用,原来后期再慢慢学习. 本篇文档,操作部分是摘自其他博客,里边的问题分析是自己在实 ...

  7. APP请求服务器数据-HttpUrlConnection

    1. 实例化URL对象 首先第一步实例化一个URL对象,传入参数为请求的数据的网址. URL url = new URL("http://www.imooc.com/api/teacher? ...

  8. 从0开始的Python学习019更多的Python内容2

    书接上文,接演Python全传 话说学了这么多Python的基础知识,也该写一点让别人看不懂的代码了. lambda lambda表达式,是一个方法的简化形似,它没有自己的代码块,它后面的语句就是它的 ...

  9. uboot的启动过程-FDT

    uboot的启动过程,省略了汇编部分之后,第一个执行函数是board_init_f(),在uboot/common目录的board_f.c中   board_init_f函数,首先初始化了全局数据 # ...

  10. 光盘安装win7系统教程

    光盘安装系统是最传统的安装系统的方法,虽然现在U盘安装和硬盘安装已经很方便,但仍有很多用户习惯光盘安装的方式,下面小编教大家如何利用光盘安装系统. 来源:https://www.haoxitongx. ...