Zookeeper---实现分布式锁

1.Zookeeper中分布式锁的实现

在这里插入图片描述
代码部分:

package com.atguigu.zk.case2;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;

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

public class DistributeLock {
    private ZooKeeper zooKeeper;
    private String connectString="hadoop102:2181,hadoop103:2181,hadoop104:2181";
    private int sessionTimeout=2000;

    //创建的临时节点
    private String currentMode;

    //前一个节点的路径
    private String waitPath;

    //获取连接状态,等待前一步骤执行完成后,程序才继续向下执行
    //初值默认为线程数量
    private CountDownLatch countDownLatch=new CountDownLatch(1);

    //获取监听结果
    private CountDownLatch waitLatch=new CountDownLatch(1);
    public DistributeLock() throws Exception {
        //获取连接
        zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                //如果连接上zk,释放countDownLatch
                if(watchedEvent.getState()== Event.KeeperState.SyncConnected)
                {
                    countDownLatch.countDown();
                }

                //waitLatch也需要释放
                if(watchedEvent.getType()==Event.EventType.NodeDeleted && watchedEvent.getPath().equals(waitPath))
                {
                    waitLatch.countDown();
                }
            }
        });
        //如果连接成功,程序会向下执行
        countDownLatch.await();

        //判断根节点/locks是否存在
        Stat exists = zooKeeper.exists("/locks", false);

        if(exists==null)
        {
            //创建/locks结点,永久结点
            zooKeeper.create("/locks","locks".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        }

    }



    //加锁
    public void zklock() throws Exception
    {
        //客户端在/locks下边创建对应的临时带序号的结点
        currentMode = zooKeeper.create("/locks/" + "seq-", null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        //判断创建的结点是否是序号最小的结点,如果是最小的,获取到锁,否则,监听它序号前的一个节点
        List<String> children = zooKeeper.getChildren("/locks", false);

        //如果只有一个节点,那么这个节点就是最小序号,获取到锁
        if(children.size()==1)
        {
            return;
        }
        else {
            //如果有多个结点
            Collections.sort(children);

            //获取结点名称seq-0000000
            String nodeName = currentMode.substring("/locks/".length());
            //通过结点名称获取结点的在children集合的位置
            int index = children.indexOf(nodeName);
            if(index==-1)
            {
                System.out.println("数据异常");
            }
            else if(index==0)
            {
                return;
            }
            else
            {
                //需要监听前一个节点的变化
                waitPath="/locks/"+children.get(index-1);
                zooKeeper.getData(waitPath,true,null);

                //等待监听
                waitLatch.await();

                //监听结束,return
                return;
            }
        }

    }

    //解锁
    public void zkunlock() throws InterruptedException, KeeperException {
        //删除结点
        zooKeeper.delete(currentMode,-1);
    }
}



测试代码:

package com.atguigu.zk.case2;

public class DistributeLockTest {
    public static void main(String[] args) throws Exception {
        DistributeLock lock1= new DistributeLock();
        DistributeLock lock2 = new DistributeLock();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    lock1.zklock();
                    System.out.println("线程1启动,获取到锁");
                    Thread.sleep(5*1000);
                    lock1.zkunlock();
                    System.out.println("线程1释放锁");
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    lock2.zklock();
                    System.out.println("线程2启动,获取到锁");
                    Thread.sleep(5*1000);
                    lock2.zkunlock();
                    System.out.println("线程2释放锁");
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }

        }).start();
    }
}

运行结果:
在这里插入图片描述

Curator框架实现分布式锁

添加依赖

<dependency>
 <groupId>org.apache.curator</groupId>
 <artifactId>curator-framework</artifactId>
 <version>4.3.0</version>
</dependency>
<dependency>
 <groupId>org.apache.curator</groupId>
 <artifactId>curator-recipes</artifactId>
 <version>4.3.0</version>
</dependency>
<dependency>
 <groupId>org.apache.curator</groupId>
 <artifactId>curator-client</artifactId>
 <version>4.3.0</version>
</dependency>

代码部分:

package com.atguigu.zk.case3;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;

public class CuratorLockTest {
    public static void main(String[] args) {
        //创建分布式锁1
        InterProcessMutex lock1 = new InterProcessMutex(getCuratorFramework(), "/locks");

        //创建分布式锁2
        InterProcessMutex lock2=new InterProcessMutex(getCuratorFramework(),"/locks");
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    lock1.acquire();
                    System.out.println("线程1获取到锁");

                    lock1.acquire();
                    System.out.println("线程1再次获取到锁");

                    Thread.sleep(5*1000);

                    lock1.release();
                    System.out.println("线程1释放锁");

                    lock1.release();
                    System.out.println("线程1再次释放锁");
                }catch (Exception e)
                {
                    System.out.println(e);
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    lock2.acquire();
                    System.out.println("线程2获取到锁");

                    lock2.acquire();
                    System.out.println("线程2再次获取到锁");

                    Thread.sleep(5*1000);

                    lock2.release();
                    System.out.println("线程2释放锁");

                    lock2.release();
                    System.out.println("线程2再次释放锁");
                }catch (Exception e)
                {
                    System.out.println(e);
                }
            }
        }).start();
    }

    private static CuratorFramework getCuratorFramework() {
        //重试的时间和次数
        ExponentialBackoffRetry exponentialBackoffRetry = new ExponentialBackoffRetry(3000, 3);

        //创建zookeeper客户端
        CuratorFramework client = CuratorFrameworkFactory.builder().connectString("hadoop102:2181,hadoop103:2181,hadoop104:2181")
                .connectionTimeoutMs(2000)
                .sessionTimeoutMs(2000)
                .retryPolicy(exponentialBackoffRetry).build();
        //客户端启动
        client.start();

        System.out.println("zookeeper启动成功");
        return client;
    }
}

运行结果:
在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值