实现过程:
首先,一个线程获取锁并调用方法生成订单号,在该线程未释放锁资源时,其他线程会被
countDownLatch阻塞,直到该线程释放锁资源。
实现模拟并发生成订单号功能
代码实现:
先导入一个依赖
<dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.10</version> </dependency>
Lock接口:
package com.doll.zookeeperlock; public interface Lock { /** * 获取锁 */ void getLock(); /** * 释放锁 */ void unLock(); }
ZookeeperAbstractLock抽象类并实现Lock
package com.doll.zookeeperlock; import org.I0Itec.zkclient.ZkClient; import java.util.concurrent.CountDownLatch; public abstract class ZookeeperAbstractLock implements Lock{ private static final String CONNECTSTRING="linuxIP地址:zookeeper端口"; // zookeeper地址 protected ZkClient zkClient=new ZkClient(CONNECTSTRING); // 连接zookeeper protected static String PATH="/lock"; // 创建节点路径 protected CountDownLatch countDownLatch; // 倒计时器作用线程阻塞 @Override public void getLock() { if(tryLock()){ System.out.println("---------------获取锁成功---------------"); }else { waitLock(); getLock(); //自己调自己 } } @Override public void unLock() { if(zkClient!=null){ zkClient.close(); System.out.println("---------------释放资源---------------"); } } /** * 是否获取锁成功 * @return */ public abstract boolean tryLock(); /** * 等待锁 */ public abstract void waitLock(); }
OrderNumGenerator订单号生成类:
package com.doll.zookeeperlock; import java.text.SimpleDateFormat; import java.util.Date; public class OrderNumGenerator { //组成订单号的变量 private static int count = 0; /** * 使用new Date()和count生成订单号 * @return */ public String getNumber() { SimpleDateFormat simpt = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); //时间类型转化 return simpt.format(new Date()) + "-" + ++count; } }
ZookeeperDistrbuteLock继承并实现分布式锁
package com.doll.zookeeperlock; import org.I0Itec.zkclient.IZkDataListener; import java.util.concurrent.CountDownLatch; public class ZookeeperDistrbuteLock extends ZookeeperAbstractLock { public boolean tryLock() { try { //创建临时节点成功,返回true zkClient.createEphemeral(PATH); return true; } catch (Exception e) { return false; } } public void waitLock() { // 使用事件监听,获取到节点被删除 IZkDataListener iZkDataListener = new IZkDataListener(){ public void handleDataChange(String s, Object o) throws Exception { } public void handleDataDeleted(String s) throws Exception { 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); } }
OrderService,main方法类
package com.doll.zookeeperlock; //Runnable模拟并发编程 public class OrderService implements Runnable { private OrderNumGenerator orderNumGenerator = new OrderNumGenerator(); private Lock lock = new com.doll.zookeeperlock.ZookeeperDistrbuteLock(); public void run() { try { lock.getLock(); getNumber(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unLock(); } } public void getNumber(){ String orderNo = orderNumGenerator.getNumber(); System.out.println(Thread.currentThread().getName() + ",orderNo=======>:" + orderNo); } public static void main(String[] args) { System.out.println("--------------模拟生成订单号开始--------------"); for (int i = 1; i <10 ; i++) { new Thread(new OrderService()).start(); } } }
运行结果图