Zookeeper分布式锁解决方案具体代码
定义一个公共资源订单生成类:
package com.itmayiedu.lock; import java.text.SimpleDateFormat; import java.util.Date; //生成订单号规则 public class OrderNumGenerator { private static int count = 0; //生成订单号规则方法 public String orderNumber() { SimpleDateFormat simpt = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); return simpt.format(new Date()) + "-" + ++count; } }
定义一个模拟多线程接口:
package com.itmayiedu.lock; //订单服务 public class OrderService implements Runnable { private OrderNumGenerator orderNumGenerator = new OrderNumGenerator(); private static Object oj = new Object(); private Lock lock=new ZookeeperDistrbuteLock(); public void run() { getNumber(); } public void getNumber() { // synchronized (oj) { lock.getLock(); String number = orderNumGenerator.orderNumber(); System.out.println(Thread.currentThread().getName() + ",生成订单号:" + number); lock.unLock(); } public static void main(String[] args) { for (int i = 0; i < 100; i++) { new Thread(new OrderService()).start(); } } }
定义锁接口:
package com.itmayiedu.lock; public interface Lock { //获取到锁的资源 public void getLock(); // 释放锁 public void unLock(); }
抽象类:
package com.itmayiedu.lock; import org.I0Itec.zkclient.ZkClient; //将重复的代码,具体业务逻辑有子类去实现. public abstract class ZookeeperAbstractLock implements Lock { private static final String CONNECT_ADDRES = "192.168.110.159:2181,192.168.110.160:2181,192.168.110.162:2181"; protected ZkClient zkClient = new ZkClient(CONNECT_ADDRES); protected static final String PATH = "/lock"; public void getLock() { // tryLock() 创建zk临时节点 如果创建成功返回true 否则返回false if (tryLock()) { System.out.println("获取到锁的资源 get lock"); } else { // 等待 waitLock(); // 重写获取锁的资源 getLock(); } } protected abstract boolean tryLock(); protected abstract void waitLock(); // 释放锁 public void unLock() { if (zkClient != null) { zkClient.close(); } System.out.println("释放锁的资源.."); } }
实现类:
package com.itmayiedu.lock; import java.util.concurrent.CountDownLatch; import org.I0Itec.zkclient.IZkDataListener; public class ZookeeperDistrbuteLock extends ZookeeperAbstractLock { private CountDownLatch countDownLatch = null; @Override protected boolean tryLock() { try { zkClient.createEphemeral(PATH); return true; } catch (Exception e) { e.printStackTrace(); return false; } } @Override protected void waitLock() { IZkDataListener zkDataListener = new IZkDataListener() { // 节点被删除的时候 事件通知 public void handleDataDeleted(String path) throws Exception { // 唤醒被等待的线程 if (countDownLatch != null) { countDownLatch.countDown(); System.out.println("删除节点....."); } } public void handleDataChange(String path, Object data) throws Exception { } }; // 注册到zkclient进行监听 zkClient.subscribeDataChanges(PATH, zkDataListener); if (zkClient.exists(PATH)) { countDownLatch = new CountDownLatch(1); try { countDownLatch.await(); } catch (Exception e) { // TODO: handle exception } } // 删除监听 zkClient.unsubscribeDataChanges(PATH, zkDataListener); } }