package Lock;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;

public class ImproveLock implements Lock{
private static String ZK_IP_PORT= "192.168.0.137:2181";
private static String LOCK_NODE = "/lock";
private ZkClient client = new ZkClient(ZK_IP_PORT);
private String currentNode = null; //当前节点
private String beforeNode = null; //前一个节点
private CountDownLatch cdl = null;

public ImproveLock(){
//创建持久节点
if(!client.exists(LOCK_NODE)){
client.createPersistent(LOCK_NODE);
}
}

@Override
public void lock() {
if(tryLock()){
return ;
}
waitForLock();
lock();
}

private void waitForLock(){
IZkDataListener listener = new IZkDataListener() {

@Override
public void handleDataDeleted(String dataPath) throws Exception {
if(cdl != null){
cdl.countDown();
}
}

@Override
public void handleDataChange(String dataPath, Object data) throws Exception {

}
};

client.subscribeDataChanges(beforeNode, listener);
if(client.exists(beforeNode)){
cdl = new CountDownLatch(1);
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
client.unsubscribeDataChanges(beforeNode, listener);
}

@Override
public void lockInterruptibly() throws InterruptedException {

}
@Override
public boolean tryLock() {
if(currentNode == null || currentNode.length() == 0){
currentNode = client.createEphemeralSequential(LOCK_NODE + "/", "lock");
System.out.println("--------------:" + currentNode);
}
//获取所有的子节点
List<String> children = client.getChildren(LOCK_NODE);
//子节点排序
Collections.sort(children);
if(currentNode.equals(LOCK_NODE + "/" + children.get(0))){
return true;
}
//找当前节点的前一个节点
int index = Collections.binarySearch(children, currentNode.substring(6));
if(index > 0){
index = index - 1;
}
beforeNode = LOCK_NODE + "/" + children.get(index);
return false;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return false;
}
@Override
public void unlock() {
client.delete(currentNode);
}
@Override
public Condition newCondition() {
return null;
}
}

---------------------test-----

package Lock;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.CountDownLatch;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LockTest {
private static Logger LOG = LoggerFactory.getLogger(LockTest.class);
private static int count = 10;
private static CountDownLatch cdl = new CountDownLatch(count);
public static void main(String[] args) {
for(int i = 0; i < count;i++){
new Thread(new Order()).start();
LOG.error("开启");
cdl.countDown();
}
}

static class Order implements Runnable{
//private DistributeLock lock = new DistributeLock();
private ImproveLock lock = new ImproveLock();
@Override
public void run() {
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.lock();
String orderId = GenorderId.genOrderId();

System.out.println(orderId);
lock.unlock();
}

}

static class GenorderId{
private static int index = 0;
public static String genOrderId(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyymmddhhmmss|SSS");
return sdf.format(new Date()) + ++index;
}
}

}

zk分布式锁-排它锁简单实现-优化版的更多相关文章

  1. zk分布式锁-排它锁简单实现

    package Lock; import java.util.concurrent.CountDownLatch;import java.util.concurrent.TimeUnit;import ...

  2. 2020-05-24:ZK分布式锁有几种实现方式?各自的优缺点是什么?

    福哥答案2020-05-24: Zk分布式锁有两种实现方式一种比较简单,应对并发量不是很大的情况.获得锁:创建一个临时节点,比如/lock,如果成功获得锁,如果失败没获得锁,返回false释放锁:删除 ...

  3. 【分布式锁的演化】终章!手撸ZK分布式锁!

    前言 这应该是分布式锁演化的最后一个章节了,相信很多小伙伴们看完这个章节之后在应对高并发的情况下,如何保证线程安全心里肯定也会有谱了.在实际的项目中也可以参考一下老猫的github上的例子,当然代码没 ...

  4. 本地锁、redis分布式锁、zk分布式锁

    本地锁.redis分布式锁.zk分布式锁 https://www.cnblogs.com/yjq-code/p/dotnetlock.html 为什么要用锁? 大型站点在高并发的情况下,为了保持数据最 ...

  5. Redis分布式锁实现简单秒杀功能

    这版秒杀只是解决瞬间访问过高服务器压力过大,请求速度变慢,大大消耗服务器性能的问题. 主要就是在高并发秒杀的场景下,很多人访问时并没有拿到锁,所以直接跳过了.这样就处理了多线程并发问题的同时也保证了服 ...

  6. 【zookeeper】Apache curator的使用及zk分布式锁实现

    上篇,本篇主要讲Apache开源的curator的使用,有了curator,利用Java对zookeeper的操作变得极度便捷. 其实在学之前我也有个疑虑,我为啥要学curator,撇开涨薪这些外在的 ...

  7. .NetCore使用Redis,StackExchange.Redis队列,发布与订阅,分布式锁的简单使用

    环境:之前一直是使用serverStack.Redis的客服端,今天来使用一下StackExchange.Redis(个人感觉更加的人性化一些,也是免费的,性能也不会差太多),版本为StackExch ...

  8. Redisson分布式锁的简单使用

    一:前言 我在实际环境中遇到了这样一种问题,分布式生成id的问题!因为业务逻辑的问题,我有个生成id的方法,是根据业务标识+id当做唯一的值! 而uuid是递增生成的,从1开始一直递增,那么在同一台机 ...

  9. .net下 本地锁、redis分布式锁、zk分布式锁的实现

    为什么要用锁? 大型站点在高并发的情况下,为了保持数据最终一致性就需要用到技术方案来支持.比如:分布式锁.分布式事务.有时候我们在为了保证某一个方法每次只能被一个调用者使用的时候,这时候我们也可以锁来 ...

随机推荐

  1. 理解Javascript的Event Loop

    一.单线程 js作为浏览器脚本语言,他的主要用途是与用户交互,以及操作DOM,这决定了它只能是单线程,为什么呢?因为假如js同时有两个线程,一个线程是在DOM上增加内容,另一个线程是删除这个节点,那么 ...

  2. 007——php字符串中的处理函数(六)

    <?php /** * 一.addslashes() 在预定义字符串前添加反斜杠 * * stripslashes() 把转义字符串前的反斜杠删除 * get_magic_quotes_gpc ...

  3. maven编译报错 -source 1.5 中不支持 lambda 表达式(转)

    原文链接:http://blog.csdn.net/kai161/article/details/50379418 在用maven编译项目是由于项目中用了jdk 1.8, 编译是报错  -source ...

  4. 判断一棵树是否为二叉搜索树(二叉排序树) python

    输入一棵树,判断这棵树是否为二叉搜索树.首先要知道什么是排序二叉树,二叉排序树是这样定义的,二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: (1)若左子树不空,则左子树上所有结点的值均小于它的 ...

  5. C/C++函数中使用可变参数

    先说明可变参数是什么,先回顾一下C++里面的函数重载,如果重复给出如下声明: int func(); int func(int); int func(float); int func(int, int ...

  6. ionic2中跨页面回传值

    1.在跳转到新页面时传入一个contactsCallback的参数,在该参数的函数定义中做出一个承诺. 注意:最开始我本来是采用如下图方式的,但是很不幸,出现了问题,问题所在就是关于这个this的作用 ...

  7. Linux修改串口irq

    /******************************************************************************* * Linux修改串口irq * 说明 ...

  8. IO的概念

    什么是IO: 在内存中存在数据交换的操作都可以认为是IO操作 和终端交互:input print 和磁盘交互:read write 和网络交互:recv send IO密集型程序:在程序执行过程中存在 ...

  9. HDU4261 Estimation

    题意 Estimation Time Limit: 40000/15000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...

  10. streamsets 丢踢无关数据

    对于不需要的数据,streamsets 可以方便的设置丢踢,我们可以通过定义require 字段或者前置条件进行配置 require(必须字段) 必须字段是必须存在一条record 中的,对于不存在的 ...