分布式锁使用zk,在zk上建立一个临时节点(有效期),分布式
使用临时节点做为锁,由于节点不容许重复。ide
若是能建立节点成功,生成订单号,若是建立节点失败,等待。spa
临时节点zk关闭,释放锁,其余节点就能够从新生成订单号。code
依赖orm
<dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.10</version> </dependency>
OrderNumber生成订单blog
public class OrderNumber {
private static Integer number=0; //生成订单号 public String getNumber(){ SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); ++number; return sdf.format(new Date())+"\t"+number; } }
OrderService打印订单号递归
public class OrderService implements Runnable{
private static OrderNumber orderNumber=new OrderNumber(); private Lock lock=new ZkLockImpl(); //生成订单 public void getOrderNumber(){ //获取锁 lock.getLock(); //生成订单号 System.out.println("订单号生成成功:"+orderNumber.getNumber()); //释放锁 lock.unLock(); } @Override public void run() { getOrderNumber(); } public static void main(String[] args) { for (int i=1;i<=100;i++){ new Thread(new OrderService()).start(); } } }
Lock文接口接口
public interface Lock { //获取锁 public void getLock(); //释放锁 public void unLock(); }
ZookeeperLock实现进程
public abstract class ZookeeperLock implements Lock{ /** * 链接地址 */ private static final String ZK_ADDRESS="0.0.0.0:2181"; protected ZkClient zkClient=new ZkClient(ZK_ADDRESS); /** * 每个进程在建立节点时,实际上就是得到了一把锁 * 若是在获取锁是发现返回值为true,表明当前没有锁,我能够使用 * 若是返回值为false,表明锁正在被占用,那么我只能等待 * */ @Override public void getLock() { //获取一把锁 if (tryLock()){ System.out.println("获取到锁资源"); }else{ //else表明锁正在被占用,请等待 waitLock(); //递归,再次获取锁 getLock(); } } @Override public void unLock() { //非等于空表明建立了订单号 if (zkClient!=null){ //关闭会话,删除节点 zkClient.close(); } } //获取锁资源 public abstract boolean tryLock(); //等待 public abstract void waitLock(); }
ZklockImpl实现资源
public class ZkLockImpl extends ZookeeperLock{ private CountDownLatch countDownLatch = null; @Override public boolean tryLock() { try { //建立临时节点 zkClient.createEphemeral("/zkTemp"); return true; }catch (Exception ex){ return false; } } @Override public void waitLock() { //监听节点是否被删除了 IZkDataListener iZkDataListener=new IZkDataListener() { @Override public void handleDataChange(String s, Object o) throws Exception { } @Override public void handleDataDeleted(String s) throws Exception { if(countDownLatch!=null){ //释放掉 countDownLatch.countDown(); } } }; //若是已经存在zkTemp节点,就等待 if(zkClient.exists("/zkTemp")){ countDownLatch=new CountDownLatch(1); System.out.println("订单号重复,请等待================================="); try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } } } }