实现过程:
首先,一个线程获取锁并调用方法生成订单号,在该线程未释放锁资源时,其他线程会被
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();
}
}
}
运行结果图