【zookeeper】利用zookeeper实现分布式锁
手写zookeeper分布式锁,测试生成订单编号
1.生成订单编号工具类
/** * TODO * * @author CSD * @date 2021-09-09 13:51 * 订单编号工具类 */ public class OrderNumCreateUtil { private static int number = 0; /** * 生成订单编号 * @return */ public String getNumber(){ return String.valueOf(++number); } }
2.订单业务类
/** * TODO * 订单业务类 * @author CSD * @date 2021-09-09 13:54 */ public class OrderService { private OrderNumCreateUtil orderNumCreateUtil = new OrderNumCreateUtil(); private ZkLock zkLock = new ZkDistributedLock(); public void getOrdNumber() { zkLock.zklock(); try { String number = orderNumCreateUtil.getNumber(); System.out.println("number = " + number); }catch (Exception e){ e.printStackTrace(); }finally { zkLock.zkUnlock(); } } }
3.zookeeper接口
/** * TODO * * @author CSD * @date 2021-09-09 14:05 */ public interface ZkLock { public void zklock(); public void zkUnlock(); }
4. 使用模板设计模式把共用的代码抽离父类
/** * TODO * * @author CSD * @date 2021-09-09 14:07 */ public abstract class ZkAbstractTemplateLock implements ZkLock { protected String path = "/zkLock"; protected CountDownLatch countDownLatch = null; public static final String ZKSERVER = "172.22.83.153:2181"; public static final Integer TIME_OUT = 45 * 1000; ZkClient zkClient = new ZkClient(ZKSERVER,TIME_OUT); @Override public void zklock() { if(tryZkLock()){ System.out.println("线程"+Thread.currentThread().getName()+":获得锁\n"); }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()+"释放锁\n\n"); } }
5.zk分布式锁具体的实现类
/** * TODO * * @author CSD * @date 2021-09-09 14:22 */ public class ZkDistributedLock extends ZkAbstractTemplateLock{ @Override public void waitZkLock() { IZkDataListener iZkDataListener = new IZkDataListener() { @Override public void handleDataChange(String dataPath, Object data) { } @Override public void handleDataDeleted(String dataPath){ if (countDownLatch != null){ countDownLatch.countDown(); } } }; 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; } } }
6.开启10个线程测试
/** * TODO * * @author CSD * @date 2021-09-09 13:57 */ public class Client { public static void main(String[] args) { for (int i = 0; i < 50; i++) { new Thread(()->{ new OrderService().getOrdNumber(); },String.valueOf(i)).start(); } } }
7.运行结果
线程6:获得锁 number = 1 线程6释放锁 线程1:获得锁 number = 2 线程1释放锁 线程5:获得锁 number = 3 线程5释放锁 线程8:获得锁 number = 4 线程8释放锁 线程2:获得锁 number = 5 线程2释放锁 线程4:获得锁 number = 6 线程4释放锁 线程0:获得锁 number = 7 线程0释放锁 线程7:获得锁 number = 8 线程7释放锁 线程3:获得锁 number = 9 线程3释放锁 线程9:获得锁 number = 10 线程9释放锁
8.所用的maven依赖
<dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency>