package com.yf.test.demo;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.util.ArrayList;
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;
public class DistributedLock implements Watcher,Lock {
static int timeout=4000;
private String lockName;
//定义锁的根结点
static String ROOT_LOCK="/dlocks";
//定义阻塞线程的型号量
CountDownLatch latch=null;
//定义一个存储zk对象
ZooKeeper zk=null;
//定义当前锁的变量
private String currentLock;
//定义存储等待锁的变量
private String waitLock;
public DistributedLock(){
}
public DistributedLock(String config,String lockName){
this.lockName=lockName;
try {
zk=new ZooKeeper(config,timeout,this);
//判断当前分布式锁的根结点是否存在
Stat exists = zk.exists(ROOT_LOCK, false);
if(exists==null){
//创建一个永久根结点
zk.create(ROOT_LOCK,new byte[0],ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
}catch (Exception e){
}
}
@Override
public void process(WatchedEvent watchedEvent) {
//监控当前有没有节点被监控,如果有就释放
if(latch!=null){
//放开等待锁线程
latch.countDown();
}
}
@Override
public void lock() {
if(tryLock()){
System.out.println(Thread.currentThread().getName()+"get lock");
return ;
}else{
waitForLock(waitLock,timeout);
}
}
private void waitForLock(String waitLock,int timeout) {
try {
Stat stat=zk.exists(ROOT_LOCK+"/"+waitLock,false);
if(stat!=null){
latch=new CountDownLatch(1);
latch.await(timeout,TimeUnit.MILLISECONDS);
latch=null;
}
}catch (Exception e){
}
}
@Override
public void lockInterruptibly() throws InterruptedException {
}
@Override
public boolean tryLock() {
try {
//拿到锁 返回
String split="_lock_";
currentLock=zk.create(ROOT_LOCK+"/"+lockName+split,new byte[0],ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
//获取根结点下面的所有子节点
List<String> list = zk.getChildren(ROOT_LOCK, false);
//定义存储排序的集合
List<String> nodes=new ArrayList<String>();
for(String child:list){
String url=child.split(split)[0];
if(url.contains(lockName)){
nodes.add(child);
}
}
//排序 从小到大排序
Collections.sort(nodes);
//判断当前节点是否是最小节点
if(currentLock.equals(ROOT_LOCK+"/"+nodes.get(0))){
return true;
}
//找到前一个节点
String currentNodeName=currentLock.substring(currentLock.lastIndexOf("/")+1);
int index = Collections.binarySearch(nodes, currentNodeName);
waitLock=nodes.get(index-1);
}catch (Exception e){
e.printStackTrace();
}
return false;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return false;
}
@Override
public void unlock() {
try {
if(zk.exists(currentLock,false)!=null){
zk.delete(currentLock,-1);
currentLock=null;
zk.close();
}
}catch (Exception e){
}
}
@Override
public Condition newCondition() {
return null;
}
}