import org.apache.zookeeper.*; import org.apache.zookeeper.data.Stat; import java.io.IOException; import java.util.List; import java.util.concurrent.CountDownLatch; /** * Created by zzq on 2019/6/25. * / Public class ZKLock the implements Watcher { Private ZooKeeper ZK; // current lock Private String currentLock; // Resource Name Private String LockName; // lock root Private String ROOT_LOCK = "/ root_lock" ; // lock root of each resource Private String tmpRootLock; // Since zookeeper monitor node status will return immediately, so it is necessary to use CountDownLatch (other mechanisms such as semaphores can be used) Private CountDownLatch LATCH; public ZKLock(String zkAddress, String lockName) { this.lockName = "" + System.nanoTime(); try { zk = new ZooKeeper(zkAddress, 30000, this); createZNode(ROOT_LOCK, CreateMode.PERSISTENT); tmpRootLock = ROOT_LOCK + "/" + lockName; createZNode (tmpRootLock, CreateMode.PERSISTENT); // can not create a temporary order of the nodes under node provisional **** zk } the catch (IOException E) { e.printStackTrace (); } catch (KeeperException e) { e.printStackTrace (); } catch (InterruptedException e) { e.printStackTrace (); } } Private void createZNode (Node String, CreateMode MODE) throws KeeperException, InterruptedException { // Get the root node status Stat STAT = zk.exists (Node, to false ); // if the root node does not exist, create a root node type persistent node IF (STAT == null ) { zk.create(node, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, mode); } } public void Lock () { the try { // Create a temporary order of the nodes under the root node, the node returns the value of the path created currentLock = zk.create (tmpRootLock + "/" + LockName, new new byte [0 ], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); // Get all provisional order of the nodes below the root node, the monitor is not provided List <String> = zk.getChildren Children (tmpRootLock, to false ); // for all the nodes in the temporal order from small to large root node children.sort ( null ); // determine whether the current node is the smallest node, if it is to acquire the lock, if not, to find their own previous node, monitoring its present state int curIndex = children.indexOf (currentLock.substring (currentLock.lastIndexOf ( "/") +. 1 )); IF (curIndex = 0! ) { // get the path of a node before the current String PREV = children.get (curIndex -. 1 ); // listener before a state of the current node , null if the node does not exist Zk.exists STAT = STAT (tmpRootLock + "/" + PREV, to true ); // Here again determines whether the node exists IF (! STAT = null ) { LATCH = new new a CountDownLatch (. 1 ); // enters a wait state lock latch.await (); latch = null; } } } catch (KeeperException e) { e.printStackTrace (); } catch (InterruptedException e) { e.printStackTrace (); } } // release the lock public void UNLOCK () { the try { // node delete created zk.delete (currentLock, -1 ); List<String> children = zk.getChildren(tmpRootLock, false); if (children.size() == 0) { zk.delete (tmpRootLock, -1 ); // Close zookeeper connected zk.close (); } } catch (InterruptedException e) { e.printStackTrace (); } catch (KeeperException e) { e.printStackTrace (); } currentLock = null; } @Override public void process(WatchedEvent event) { if (this.latch != null) { latch.countDown(); } } public static void main(String[] args) throws Exception { for (int i = 0; i < 7; i++) { // new Thread(new Runnable() { // @Override // public void run() { // ZKLock lock = new ZKLock("10.10.210.123:2181", "lock"); // SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // lock.lock(); // } // }).start(); } ZKLock lock = new ZKLock("10.10.210.123:2181", "L1"); lock.lock(); ZKLock lock1 = new ZKLock("10.10.210.123:2181", "L2"); lock1.lock(); lock1.unlock(); lock.unlock(); String uu = ""; } }