zoukankan      html  css  js  c++  java
  • zookeeper实现分布式锁

    通过用zk创建临时节点的特性,实现分布式锁;
    当前只有一个线程创建成功,然后close之后,该节点被删除;
    其他线程可以再次争抢。

    实现一个生成订单号,几个线程生成几个订单号,模仿多jvm对应多个线程

    public class OrderNumCreateUtil {
    
    	private static int number = 0;
    	public String getOrderNumber(){
    		return "	 生成订单号:" + (++ number);
    	}
    }
    
    public interface ZkLock {
    
    	public void zklock();
    	public void zkUnlock();
    }
    

    利用模板方法模式,把需要经常改的东西抽象出来,交给子类去实现

    public abstract class ZkAbstractLock implements ZkLock{
    	
    	public static final String ZKSERVER = "47.100.41.55:2181";
    	public static final int TIME_OUT = 45 * 1000;
    	ZkClient zkClient = new ZkClient(ZKSERVER, TIME_OUT);
    	
    	protected String path = "/zklock0401";
    	protected CountDownLatch countDownLatch = null;
    	
    	@Override
    	public void zklock() {
    		if(tryZkLock()){
    			System.out.println(Thread.currentThread().getName() + "	 占用锁成功。");
    		}else{
    			waitZkLock();
    			zklock();
    		}
    	}
    
    	public abstract  void waitZkLock();
    
    	public abstract boolean tryZkLock();
    
    	@Override
    	public void zkUnlock() {
    		if(zkClient != null){
    			zkClient.close();
    		}
    		System.out.println(Thread.currentThread().getName() + "	 释放锁成功。");
    		System.out.println();
    		System.out.println();
    	}
    }
    
    public class ZkDistributedLock extends ZkAbstractLock{
    
    	@Override
    	public void waitZkLock() {
    		//监听path,1,数据是否改变或删除
    		IZkDataListener iZkDataListener = new IZkDataListener() {
    			
    			@Override
    			public void handleDataDeleted(String arg0) throws Exception {
    				if(countDownLatch != null){
    					countDownLatch.countDown();
    				}
    			}
    			
    			@Override
    			public void handleDataChange(String arg0, Object arg1) throws Exception {
    				
    			}
    		};
    		zkClient.subscribeDataChanges(path, iZkDataListener);
    		if(zkClient.exists(path)){
    			//只能等着,因为锁已经被其他线程占领了
    			countDownLatch = new CountDownLatch(1);
    			try {
    				countDownLatch.await();
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    		zkClient.unsubscribeDataChanges(path, iZkDataListener);
    	}
    
    	@Override
    	public boolean tryZkLock() {
    		try {
    			//创建临时节点
    			zkClient.createEphemeral(path);
    			return true;
    		} catch (Exception e) {
    			return false;
    		}
    	}
    }
    
    public class OrderService {
    
    	private OrderNumCreateUtil orderNumCreateUtil = new OrderNumCreateUtil();
    	private ZkLock zklock = new ZkDistributedLock();
    	
    	public void getOrderNum(){
    		zklock.zklock();
    		try {
    			System.out.println("获得编号:----->:" + orderNumCreateUtil.getOrderNumber());
    		} catch (Exception e) {
    			
    		}finally{
    			zklock.zkUnlock();
    		}
    	}
    }
    
    public class Client {
    	public static void main(String[] args) {
    		for (int i = 0; i < 20; i++) {
    			new Thread(()->{
    				//模仿多jvm
    				new OrderService().getOrderNum();
    			},String.valueOf(i)).start();
    		}
    	}
    }
    

    输出:

    19	 占用锁成功。
    获得编号:----->:	 生成订单号:1
    19	 释放锁成功。
    
    
    12	 占用锁成功。
    获得编号:----->:	 生成订单号:2
    12	 释放锁成功。
    
    
    9	 占用锁成功。
    获得编号:----->:	 生成订单号:3
    9	 释放锁成功。
    
    
    7	 占用锁成功。
    获得编号:----->:	 生成订单号:4
    0	 占用锁成功。
    获得编号:----->:	 生成订单号:5
    7	 释放锁成功。
    
    
    0	 释放锁成功。
    
    
    17	 占用锁成功。
    获得编号:----->:	 生成订单号:6
    17	 释放锁成功。 
    
    
    4	 占用锁成功。
    获得编号:----->:	 生成订单号:7
    4	 释放锁成功。
    
    
    6	 占用锁成功。
    获得编号:----->:	 生成订单号:8
    6	 释放锁成功。
    
    
    14	 占用锁成功。
    获得编号:----->:	 生成订单号:9
    14	 释放锁成功。
    
    
    11	 占用锁成功。
    获得编号:----->:	 生成订单号:10
    11	 释放锁成功。
    
    
    10	 占用锁成功。
    获得编号:----->:	 生成订单号:11
    10	 释放锁成功。
    
    
    2	 占用锁成功。
    获得编号:----->:	 生成订单号:12
    2	 释放锁成功。
    
    
    18	 占用锁成功。
    获得编号:----->:	 生成订单号:13
    18	 释放锁成功。
    
    
    15	 占用锁成功。
    获得编号:----->:	 生成订单号:14
    15	 释放锁成功。
    
    
    13	 占用锁成功。
    获得编号:----->:	 生成订单号:15
    13	 释放锁成功。
    
    
    8	 占用锁成功。
    获得编号:----->:	 生成订单号:16
    8	 释放锁成功。
    
    
    16	 占用锁成功。
    获得编号:----->:	 生成订单号:17
    16	 释放锁成功。
    
    
    5	 占用锁成功。
    获得编号:----->:	 生成订单号:18
    5	 释放锁成功。
    
    
    3	 占用锁成功。
    获得编号:----->:	 生成订单号:19
    3	 释放锁成功。
    
    
    1	 占用锁成功。
    获得编号:----->:	 生成订单号:20
    1	 释放锁成功。
    
  • 相关阅读:
    C# 中的委托和事件
    SQLserver2000与2005同时安装的问题
    又到毕业时
    WCF服务发布和调用IIS服务
    进销存取项目总结
    URL
    undefined reference to `android::Mutex::lock()'
    关于 ffmpeg ‘UINT64_C’ was not declared in this scope 的错误
    Ti 的 OMX_Core
    linux Perforce 使用
  • 原文地址:https://www.cnblogs.com/kaka-qiqi/p/14927439.html
Copyright © 2011-2022 走看看