分佈式鎖使用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(); } } } }