• Zookeeper


    Zookeeper实战分布式锁

    场景描述

    线程高并发场景下,生成唯一的订单编号

    :2017-10-14-20-52-33-01

       序号

     

    代码

    Lock接口

    /**
     * 获取锁和释放锁真正实现的类
     */
    public class ZkLockImpl extends ZookeeperLock{
        private CountDownLatch countDownLatch = null;
    
    
        @Override
        public boolean tryLock() {
            try {
                //创建临时节点
                zkClient.createEphemeral("/zkTemp");
                return true;
            }catch (Exception ex){
                return false;
            }
        }
    
        @Override
        public void waitLock() {
            //监听节点是否是删除了
            IZkDataListener iZkDataListener=new IZkDataListener() {
                @Override
                public void handleDataChange(String s, Object o) throws Exception {
    
                }
    
                @Override
                public void handleDataDeleted(String s) throws Exception {
                    if(countDownLatch!=null){
                        //释放掉
                        countDownLatch.countDown();
                    }
                }
            };
    
            //如果已经存在zkTemp节点,就等待
            if(zkClient.exists("/zkTemp")){
                countDownLatch=new CountDownLatch(1);
                System.out.println("订单号重复,请等待=================================");
                try {
                    countDownLatch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    OrderNumber

    /**
     * 订单产生的类
     */
    public class OrderNumber {
        private static Integer number=0;
        //生成订单号
        public String getNumber(){
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
            ++number;
            return sdf.format(new Date())+"	"+number;
        }
    }

    ZookeeperLock

    public abstract class ZookeeperLock implements Lock{
        /**
         * 创建zkClient连接对象
         */
        private static final String ZK_ADDRESS="0.0.0.0:2181";
    
        protected ZkClient zkClient=new ZkClient(ZK_ADDRESS);
    
    
        /**
         * 每一个进程在创建节点时,实际上就是获得了一把锁,如果在获取锁是发现返回值为true,代表当前没有锁,我可以使用,如果返回值为false,代表锁正在被占用,那么我只能等待
         * @return
         */
        @Override
        public void getLock() {
            //获取一把锁
            if(tryLock()){
                System.out.println("获取到锁资源");
            }else{
                //当返回值为false时,代表当前锁正在被使用,等待
                waitLock();
                //等待之后我得再次获取,我不再次获取我怎么能得到锁资源
                getLock();
            }
    
        }
    
    
        /**
         * 释放锁,zk关闭
         */
        @Override
        public void unLock() {
            if(zkClient!=null){
                zkClient.close();
            }
        }
    
    
        //获取锁资源
        public abstract boolean tryLock();
    
    
        //等待
        public abstract void waitLock();
    }
    
     

    OrderService

    /**
     * 订单业务处理类
     */
    public class OrderService implements Runnable{
        private static OrderNumber orderNumber=new OrderNumber();
        private Lock lock=new ZkLockImpl();
    
    
    
        //生成订单
        public void getOrderNumber(){
            //同步代码块:多个线程访问同一个资源时
            /*synchronized (orderNumber){
    
            }*/
    
    
            //获取锁
            lock.getLock();
            System.out.println("当前生成的订单编号为:"+orderNumber.getNumber());
            //释放锁
            lock.unLock();
    
        }
    
        @Override
        public void run() {
            getOrderNumber();
        }
    
        public static void main(String[] args) {
            //生成100个线程
            for(int i=1;i<=1000;i++){
                new Thread(new OrderService()).start();
            }
        }
    
    }

    ZKLockImpl

    /**
     * 获取锁和释放锁真正实现的类
     */
    public class ZkLockImpl extends ZookeeperLock{
        private CountDownLatch countDownLatch = null;
    
    
        @Override
        public boolean tryLock() {
            try {
                //创建临时节点
                zkClient.createEphemeral("/zkTemp");
                return true;
            }catch (Exception ex){
                return false;
            }
        }
    
        @Override
        public void waitLock() {
            //监听节点是否是删除了
            IZkDataListener iZkDataListener=new IZkDataListener() {
                @Override
                public void handleDataChange(String s, Object o) throws Exception {
    
                }
    
                @Override
                public void handleDataDeleted(String s) throws Exception {
                    if(countDownLatch!=null){
                        //释放掉
                        countDownLatch.countDown();
                    }
                }
            };
    
            //如果已经存在zkTemp节点,就等待
            if(zkClient.exists("/zkTemp")){
                countDownLatch=new CountDownLatch(1);
                System.out.println("订单号重复,请等待=================================");
                try {
                    countDownLatch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
  • 相关阅读:
    面试题:求最大子数组的合以及起始终止位
    星级推荐,列举一下2018年购入的书籍
    Idea Live Templates
    oracle 学习随笔一: 字段大小写
    gitignore 文件生效办法
    同台服务器 部署多个tomcat 需要做的修改
    FastJson 序列化与反序列化一些说明
    记一次Log4j2日志无法输出的 心酸史
    关于.net中使用reportview所需注意
    团队作业——总结
  • 原文地址:https://www.cnblogs.com/szhhhh/p/11949687.html
Copyright © 2020-2023  润新知