zookeeper分布式锁DEMO

//本例采用临时顺序目录节点实现分布式锁

package zookeeper;


import java.io.IOException;
import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.Watcher.Event.KeeperState;


public class ConnectionWatcher implements Watcher {

 private static final int SESSION_TIMEOUT = 5000;

 protected ZooKeeper zk;
 private CountDownLatch connectedSignal = new CountDownLatch(1);

 public void connect(String hosts) throws IOException, InterruptedException {
  zk = new ZooKeeper(hosts, SESSION_TIMEOUT, this);
  connectedSignal.await();
 }

 @Override
 public void process(WatchedEvent event) {
  if (event.getState() == KeeperState.SyncConnected) {
   connectedSignal.countDown();
  }
 }

 public void close() throws InterruptedException {
  zk.close();
 }
}

 

 

package zookeeper;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.data.Stat;

 
public class DistributedLock extends ConnectionWatcher {

 public String join(String groupPath)
   throws KeeperException, InterruptedException {
 
  String path = groupPath + "/lock-" + zk.getSessionId() + "-";
  
  //建立一个顺序临时节点
  String createdPath = zk.create(path, null/* data */,
    Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
  
  return createdPath;
 }

 
 /**
  * 检查本客户端是否得到了分布式锁
  * @param groupPath
  * @param myName
  * @return
  * @throws KeeperException
  * @throws InterruptedException
  */
 public boolean checkState(String groupPath,String myName) throws KeeperException, InterruptedException{
  
  List<String> childList =  zk.getChildren(groupPath, false);
  String[] myStr = myName.split("-");
  long myId = Long.parseLong(myStr[2]);
  System.out.println("myId======"+myId);
  
  boolean minId = true;
  for (String childName : childList) {
   String[] str = childName.split("-");
   long id = Long.parseLong(str[2]);
   System.out.println("id======"+id);
   if (id < myId) {
    System.out.println("当前节点不是最小节点");
    minId = false;
    break;
   }
  }
  
  if (minId) {
   System.out.println(new Date() + "恭喜你,得到分布锁! myId:" + myId);
   
   return true;
  }else {
   System.out.println(new Date() + "很遗憾,继续努力吧!  myId:" + myId);
   
   return false;
  }  
 }
 
 /**
  * 若本客户端没有得到分布式锁,则进行监听当前节点的上一节点
  * @param groupPath
  * @param myName
  * @throws KeeperException
  * @throws InterruptedException
  */
 public void listenNode(final String groupPath, final String myName) throws KeeperException, InterruptedException{
  
  List<String> childList =  zk.getChildren(groupPath, false);
  
  String[] myStr = myName.split("-");
  long myId = Long.parseLong(myStr[2]);
  List<Long> idList = new ArrayList<Long>();
  Map<Long, String> sessionMap = new HashMap<Long, String>();
  
  for (String childName : childList) {
   String[] str = childName.split("-");
   long id = Long.parseLong(str[2]);
   idList.add(id);
   sessionMap.put(id, str[1]+"-"+str[2]);
  }
  
  Collections.sort(idList);
  System.out.println("idList----"+idList);
  int i = idList.indexOf(myId);
  if (i<=0) {
   throw new IllegalArgumentException("数据异常!");
  }
  
  //得到前面的一个节点
  long headId = idList.get(i-1);
  System.out.println("headId======"+headId);
  String headPath = groupPath + "/lock-" + sessionMap.get(headId);
  System.out.println("添加监听:" + headPath);
  
  Stat stat = zk.exists(headPath, new Watcher(){

   @Override
   public void process(WatchedEvent event) {
    System.out.println("已经触发了" + event.getType() + "事件!");
    
    try {
     while(true){
      if (checkState(groupPath,myName)) {
       Thread.sleep(3000);
       System.out.println(new Date() + " 系统关闭!");
       System.exit(0);
      }
      
      Thread.sleep(3000);

     }
    } catch (KeeperException e) {
     e.printStackTrace();
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    
   }
   
  });

  System.out.println(stat);
  
 }
 
 
 public static void main(String[] args) throws Exception {
  DistributedLock lock = new DistributedLock();
  lock.connect("192.168.131.4:2181,192.168.131.3:2181");
  //zookeeper的根节点;运行本程序前,需要提前生成
  String groupName = "zkRoot";
  String memberName = "_locknode_";
  String path = "/" + groupName + "/" + memberName;
  
  String myName = lock.join(path);
  if (!lock.checkState(path, myName)) {
   lock.listenNode(path, myName);
  }
  
  Thread.sleep(Integer.MAX_VALUE);
  
  lock.close();
 }
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值