zooKeeper实现分布式锁

利用zooKeeper的节点写入之后不能再次写入的特点做分布式锁,也可以利用有序节点,然后判断当前的节点是否是最后一个节点,目前我所知道的就这两种,如果你有更好的,希望你能在下方评论里打出,或者给我一个连接

这儿只给出利用节点不能再次写入的特点的代码,话不多说,直接上代码

package upAndDownLine.zooLock;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

import java.io.IOException;

public class ZookeeperLock {
    //集群的地址 ip:端口;这儿测试的时候可以使用单机模式
    private static String connectionStr = "masterNode1:2181,slaveNode1:2181,slaveNode2:2181";
    private static ZooKeeper zooKeeper = null;
    private static String PATH="/lockss";
    //要竞争的资源的总数 :小姐姐的人数
    private static int n = 100;
    //模拟有多少人来竞争这个共享资源 :单身汪的人数
    private static int i = 120;
    //计算有多少人竞争共享资源失败 :没带走小姐姐的人数
    private static int m = 0;
    //要竞争的资源标示  :小姐姐们的标示
    private static String id ="123";

    public static boolean tryLock() {
        try {
            
            boolean b = true;
            //建立链接
            zooKeeper = new ZooKeeper(connectionStr,5000,null);
            //判断zookeeper是否已经存在 PATH 这个节点
            Stat stat = zooKeeper.exists(PATH, false);
            //如果为空则创建这个节点
            if (stat == null){
                zooKeeper.create(PATH,"100".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            }
            //循环创建直到创建成功
            while (b){
                //创建零时节点
                try {
                    zooKeeper.create(PATH +"/"+id, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
                    
                } catch (KeeperException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //创建成功则跳出循环
                b = false;
            }
            //创建成功则加锁成功
            return true;

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 加锁成功后执行逻辑代码完成后删除该锁
     */
    public static void unLock(){
        try {
            zooKeeper.delete(PATH+"/"+id,-1);
        } catch (InterruptedException e) {
//            e.printStackTrace();
        } catch (KeeperException e) {
//            e.printStackTrace();
        }
    }

    public static void thread(){
        for (int f=0;f < i; f++){
            new Thread() {
                public void run(){
                    try {
                        //模拟执行逻辑操作的耗时操作 :单身汪展示自己的实力
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Long start = System.currentTimeMillis();
                    //只对涉及共享资源的数据进行加锁,减小锁的力度
                    if (tryLock()){
                        if (n > 0){
                            System.out.println("当前小姐姐还有"+(--n));
                            //解锁
                            unLock();
                        }else {
                            System.out.println("当前小姐姐已被单身汪带走完了,请下次早来");
                            //没有竞争到共享资源的人数+1
                            m++;
                        }

//                        System.out.println((System.currentTimeMillis()-start)+"ms");
                    }
                }
            }.start();
        }
    }

    public static void main(String[] args) {
        System.out.println("目前单身汪剩余人数:"+i);
        System.out.println("目前小姐姐人数"+n);
        thread();
        try {
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("目前单身汪剩余人数:"+m);
        System.out.println("目前小姐姐人数"+n);
    }
}

这儿使用多线程来模拟多人运动

相关推荐