zookeeper分布式锁实例

<dependency>
	<groupId>com.101tec</groupId>
	<artifactId>zkclient</artifactId>
	<version>0.10</version>
</dependency>
如果有一把锁,被多个人给竞争,此时多个人会排队,第一个拿到锁的人会执行,然后释放锁;后面的每个人都会去监听**排在自己前面**的那个人创建的 node 上,一旦某个人释放了锁,排在自己后面的人就会被 zookeeper 给通知,一旦被通知了之后,就 ok 了,自己就获取到了锁,就可以执行代码了。
```java
public class ZooKeeperDistributedLock {

    //private ZooKeeper zk;
    private ZkClient zk;
    private String locksRoot = "/locks";
    private String productId;
    private String waitNode;
    private String lockNode;
    private CountDownLatch latch;
    private int sessionTimeout = 30000;

    public ZooKeeperDistributedLock() {

        try {
                                         
            String address="192.168.31.187:2181,192.168.31.19:2181,192.168.31.227:2181";
            zk = new ZkClient(address, sessionTimeout, sessionTimeout);
        } catch (IOException e) {
            throw new LockException(e);
        } catch (KeeperException e) {
            throw new LockException(e);
        } catch (InterruptedException e) {
            throw new LockException(e);
        }
    }


    public void acquireDistributedLock() {
        try {
            if (this.tryLock()) {
                return;
            } else {
                waitForLock(waitNode, sessionTimeout);
                acquireDistributedLock();
            }
        } catch (KeeperException e) {
            throw new LockException(e);
        } catch (InterruptedException e) {
            throw new LockException(e);
        }
    }

    public boolean tryLock() {
        try {
 		   
            lockNode = this.client.createEphemeralSequential(locksRoot+ "/", "1");
   
            // 看看刚创建的节点是不是最小的节点
	    // locks:10000000000,10000000001,10000000002
            List<String> locks = zk.getChildren(locksRoot);
            Collections.sort(locks);
	
            if(lockNode.equals(locksRoot+"/"+ locks.get(0))){
                System.out.println(Thread.currentThread().getName() + ":获取锁成功");
                //如果是最小的节点,则表示取得锁
                return true;
            }
	
            //如果不是最小的节点,找到比自己小1的节点
	  int previousLockIndex = -1;
            for(int i = 0; i < locks.size(); i++) {
		if(lockNode.equals(locksRoot + “/” + locks.get(i))) {
	         	    previousLockIndex = i - 1;
		    break;
		}
	   }
	   
	   this.waitNode = locks.get(previousLockIndex);
        } catch (KeeperException e) {
            throw new LockException(e);
        } catch (InterruptedException e) {
            throw new LockException(e);
        }
        return false;
    }

    private boolean waitForLock(String waitNode, long waitTime) throws 
        InterruptedException, KeeperException {
        Stat stat = zk.exists(locksRoot + "/" + waitNode, true);
        this.latch = new CountDownLatch(1);
        
        IZkDataListener listener = new IZkDataListener() {
 	    @Override			
            public void handleDataChange(String arg0, Object arg1) throws Exception { 			
            } 			
            @Override			
            public void handleDataDeleted(String arg0) 
                throws Exception {	            
                    System.out.println("节点被删除了,开始抢锁");
	            cdl.countDown();
            } 		
        };	
	
        // 完成watcher注册		
        this.client.subscribeDataChanges(beforePath, listener);

        if (stat != null) {
            this.latch.await(waitTime, TimeUnit.MILLISECONDS);
            this.latch = null;
        }

        // 取消注册
	this.client.unsubscribeDataChanges(beforePath, listener);
        return true;
    }

    public void unlock() {
        try {
            // 删除/locks/10000000000节点
            // 删除/locks/10000000001节点
            System.out.println("unlock " + lockNode);
            zk.delete(lockNode);
            System.out.println(Thread.currentThread().getName() 
                + "所有锁释放成功:删除zk节点");
            lockNode = null;
            zk.close();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (KeeperException e) {
            e.printStackTrace();
        }
    }

    public class LockException extends RuntimeException {
        private static final long serialVersionUID = 1L;

        public LockException(String e) {
            super(e);
        }

        public LockException(Exception e) {
            super(e);
        }
    }
}
public class OrderCodeGenerator {

    private int i = 0;

    public String getOrderCode() {

	Date now = new Date();

	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-");

	return sdf.format(now) + ++i;

    }
}

public class OrderServiceImplWithZkDis implements OrderService {

 
	private static OrderCodeGenerator org = new OrderCodeGenerator();


	private Lock lock = new ZooKeeperDistributedLock();

 
	@Override

	public void createOrder() {

		String orderCode = null;

 		try {

			lock.acquireDistributedLock();

 			orderCode = org.getOrderCode();

			//TestReLock();

			System.out.println(Thread.currentThread().getName() + "生成订单:" + orderCode);

		} catch (Exception e) {

			e.printStackTrace();

		} finally {

			lock.unlock();

		}

	}

 
        /**
	public void TestReLock() {

		lock.acquireDistributedLock();

		System.out.println(Thread.currentThread().getName() + "测试重入锁成功...");

		lock.unlock();

	}
        **/ 
 

	public static void main(String[] args) {

		int num = 5;

		CyclicBarrier cyclicBarrier = new CyclicBarrier(num);
 
		for (int i = 0; i < num; i++) {

			new Thread(new Runnable() {

				@Override

				public void run() {

					OrderService orderService = new OrderServiceImplWithZkDis();

					System.out.println(Thread.currentThread().getName() + ": 我准备好了");

					try {
						cyclicBarrier.await();

					} catch (Exception e) {

						e.printStackTrace();

					}

 					orderService.createOrder();

				}

			}).start();

		}

	}

 }
Thread-2:我准备好了
Thread-3:我准备好了
Thread-1:我准备好了
Thread-5:我准备好了
Thread-4:我准备好了
Thread-4:获取锁成功
Thread-4生成订单:2018-07-12-13-12-09-1
Thread-4所有锁释放成功:删除ZK节点
节点删除了,开始抢锁
Thread-5:获取锁成功
Thread-5生成订单:2018-07-12-13-12-11-2
Thread-5所有锁释放成功:删除ZK节点
节点删除了,开始抢锁
Thread-2:获取锁成功
Thread-2生成订单:2018-07-12-13-12-14-3
Thread-2所有锁释放成功:删除ZK节点
节点删除了,开始抢锁
Thread-3:获取锁成功
Thread-3生成订单:2018-07-12-13-12-17-4
Thread-3所有锁释放成功:删除ZK节点
节点删除了,开始抢锁
Thread-1:获取锁成功
Thread-1生成订单:2018-07-12-13-12-21-5
Thread-1所有锁释放成功:删除ZK节点
节点删除了,开始抢锁

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值