使用zookeeper API实现分布式锁

人盡茶涼 提交于 2020-10-27 04:56:36

1、使用zookeeper API实现分布式锁

DistributedLock.java

import java.io.IOException;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

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

public class DistributedLock implements Lock,Watcher{
   
   
	
	private ZooKeeper zk = null;
	private String ROOT_LOCK = "/locks003";//定义根节点
	private String WAIT_LOCK;//等待前一个锁
	private String CURRENT_LOCK;//表示当前的锁
	private CountDownLatch countDownLatch;
	
	public DistributedLock() {
   
   
		try {
   
   
			zk = new ZooKeeper("192.168.1.102:2181,192.168.1.102:2182,192.168.1.102:2183",4000,this);
			// 判断根节点是否存在
			Stat stat = zk.exists(ROOT_LOCK, false);
			if(stat == null) {
   
   
				zk.create(ROOT_LOCK, "0".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
			}
			
		} catch (IOException e) {
   
   
			e.printStackTrace();
		} catch (KeeperException e) {
   
   
			e.printStackTrace();
		} catch (InterruptedException e) {
   
   
			e.printStackTrace();
		}
	}
	
	@Override
	public boolean tryLock() {
   
   
		try {
   
   
			// 创建临时有序节点
			CURRENT_LOCK = zk.create(ROOT_LOCK + "/" , "0".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
		    System.out.println(Thread.currentThread().getName() + "->" + CURRENT_LOCK + " try lock ");
		    
		    List<String> childrens = zk.getChildren(ROOT_LOCK, false);
		    SortedSet<String> sortedSet =  new TreeSet();//定义一个集合进行排序
		    for(String children : childrens) {
   
   
		    	sortedSet.add(ROOT_LOCK + "/" + children);
		    }
		    
		    String firstNode = sortedSet.first();//获得当前所有子节点中最小的节点
		    SortedSet<String> lessThenMe = ((TreeSet<String>)sortedSet).headSet(CURRENT_LOCK);
		    // 如果当前节点和集合中的最小节点相同,表示获得锁
		    if(CURRENT_LOCK.equals(firstNode)) {
   
   
		    	return true;
		    }
		    
		    if(!lessThenMe.isEmpty()) {
   
   
		    	// 获得比当前节点更小的最后一个节点,设置给WAIT_LOCK
		    	WAIT_LOCK = lessThenMe.last();
		    }
		    
		      
		} catch (KeeperException | InterruptedException e) {
   
   
			e.printStackTrace();
		}
		return false;
	}
	
	@Override
	public void process(WatchedEvent event) {
   
   
		if(this.countDownLatch != null) {
   
   
			this.countDownLatch.countDown();
		}
	}
	
	@Override
	public void lock() {
   
   
		if(this.tryLock()) {
   
   
			System.out.println(Thread.currentThread().getName() + "->" + CURRENT_LOCK + "->" + " get lock success " );
			return;
		}
		try {
   
   
			waitForLock(WAIT_LOCK);//没有获得锁,继续等待获得锁
			
		} catch (KeeperException e) {
   
   
			e.printStackTrace();
		} catch (InterruptedException e) {
   
   
			e.printStackTrace();
		}
	}

	private boolean waitForLock(String prev) throws KeeperException, InterruptedException {
   
   
		Stat stat = zk.exists(prev, true);//监听当前节点的上一个节点
		if(stat != null) {
   
   
			System.out.println(Thread.currentThread().getName() + " -> wait lock " + prev + " 释放 ");
			countDownLatch = new CountDownLatch(1);
			countDownLatch.await();
			System.out.println(Thread.currentThread().getName() + " -> get lock success -- / -- ");
		}
		return true;
	}
	
	@Override
	public void lockInterruptibly() throws InterruptedException {
   
   
		
	}

	@Override
	public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
   
   
		return false;
	}

	@Override
	public void unlock() {
   
   
		System.out.println(Thread.currentThread().getName() + " 释放锁 " + CURRENT_LOCK);
		try {
   
   
			zk.delete(CURRENT_LOCK, -1);
            CURRENT_LOCK = null;   
			zk.close();
		} catch (InterruptedException e) {
   
   
			e.printStackTrace();
		} catch (KeeperException e) {
   
   
			e.printStackTrace();
		}
	}

	@Override
	public Condition newCondition() {
   
   
		return null;
	}
	
}

测试程序:DistributedLockTest.java

public class DistributedLockTest {
   
   
	
	public static void main(String[] args) throws IOException {
   
   
		final CountDownLatch countDownLatch = new CountDownLatch(10);
		for (int i = 0; i < 10; i++) {
   
   
			Thread thread =new Thread(new Runnable() {
   
   
				@Override
				public void run() {
   
   
					try {
   
   
						countDownLatch.await();
						DistributedLock distributedLock = new DistributedLock();
						distributedLock.lock();
                        						
					} catch (InterruptedException e) {
   
   
						e.printStackTrace();
					}
				}
			},"Thread-" + i);
			thread.start();
			countDownLatch.countDown();
		}
		
		System.in.read();
	}
     	 
}

在这里插入图片描述
在这里插入图片描述

2、使用Curator客户端实现分布式锁

参考:Apache Curator+Zookeeper 实现分布式锁 入门篇

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!