iamdll 2020-06-11
利用zooKeeper的节点写入之后不能再次写入的特点做分布式锁,也可以利用有序节点,然后判断当前的节点是否是最后一个节点,目前我所知道的就这两种,如果你有更好的,希望你能在下方评论里打出,或者给我一个连接
这儿只给出利用节点不能再次写入的特点的代码,话不多说,直接上代码
package upAndDownLine.zooLock; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.ZooDefs; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.data.Stat; import java.io.IOException; public class ZookeeperLock { //集群的地址 ip:端口;这儿测试的时候可以使用单机模式 private static String connectionStr = "masterNode1:2181,slaveNode1:2181,slaveNode2:2181"; private static ZooKeeper zooKeeper = null; private static String PATH="/lockss"; //要竞争的资源的总数 :小姐姐的人数 private static int n = 100; //模拟有多少人来竞争这个共享资源 :单身汪的人数 private static int i = 120; //计算有多少人竞争共享资源失败 :没带走小姐姐的人数 private static int m = 0; //要竞争的资源标示 :小姐姐们的标示 private static String id ="123"; public static boolean tryLock() { try { boolean b = true; //建立链接 zooKeeper = new ZooKeeper(connectionStr,5000,null); //判断zookeeper是否已经存在 PATH 这个节点 Stat stat = zooKeeper.exists(PATH, false); //如果为空则创建这个节点 if (stat == null){ zooKeeper.create(PATH,"100".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } //循环创建直到创建成功 while (b){ //创建零时节点 try { zooKeeper.create(PATH +"/"+id, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); } catch (KeeperException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } //创建成功则跳出循环 b = false; } //创建成功则加锁成功 return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 加锁成功后执行逻辑代码完成后删除该锁 */ public static void unLock(){ try { zooKeeper.delete(PATH+"/"+id,-1); } catch (InterruptedException e) { // e.printStackTrace(); } catch (KeeperException e) { // e.printStackTrace(); } } public static void thread(){ for (int f=0;f < i; f++){ new Thread() { public void run(){ try { //模拟执行逻辑操作的耗时操作 :单身汪展示自己的实力 Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } Long start = System.currentTimeMillis(); //只对涉及共享资源的数据进行加锁,减小锁的力度 if (tryLock()){ if (n > 0){ System.out.println("当前小姐姐还有"+(--n)); //解锁 unLock(); }else { System.out.println("当前小姐姐已被单身汪带走完了,请下次早来"); //没有竞争到共享资源的人数+1 m++; } // System.out.println((System.currentTimeMillis()-start)+"ms"); } } }.start(); } } public static void main(String[] args) { System.out.println("目前单身汪剩余人数:"+i); System.out.println("目前小姐姐人数"+n); thread(); try { Thread.sleep(20000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("目前单身汪剩余人数:"+m); System.out.println("目前小姐姐人数"+n); } }
这儿使用多线程来模拟多人运动