利用zookeeper临时节点和事件监听实现分布式锁,分布式订单号生成实例
1、OrderNumGenerator.java
// 时间戳+递增序号生成订单号
public class OrderNumGenerator {
private static int count;
public String getNum(){
SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
return sdf.format(new Date())+"-"+ ++count;
}
}
2、OrderService.java
public class OrderServiceimplements Runnable {
private OrderNumGeneratororderNumGenerator =new OrderNumGenerator();
private ZkLocklock =new ZkLock();
@Override
public void run() {
getNumber();
}
private void getNumber() {
try {
lock.lock();
String number =orderNumGenerator.getNum();
System.out.println(Thread.currentThread().getName() +", 获取的number:" + number);
}catch (Exception e) {
}finally {
lock.unlock();
}
}
}
3、ZkLock.java
public class ZkLock {
private static final StringCONNECT_STRING ="192.168.0.106:2181";
private static final int SESSION_TIMEOUT =5000;
private ZkClientzkClient =new ZkClient(CONNECT_STRING,SESSION_TIMEOUT);
private StringlockNode ="/lockNode";
private CountDownLatchcountDownLatch =null;
//获取锁,即创建临时节点成功的获取锁
public void lock(){
try {
zkClient.createEphemeral(lockNode);
System.out.println(Thread.currentThread().getName()+",获得锁");
}catch (Exception e) {
waitLock();
}
}
//等待获取锁
private void waitLock(){
// zk事件监听,监听lockNode节点是否被删除,如果被删除则可以重新获取锁
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计数变为0
countDownLatch.countDown();
}
}
});
zkClient.subscribeDataChanges(lockNode, iZkDataListener);
if(countDownLatch ==null){
countDownLatch =new CountDownLatch(1);
}
try {
// countDownLatch不为0,则一直等待
countDownLatch.await();
}catch (Exception e){
}
zkClient.unSubscribeDataChanges(lockNode, iZkDataListener);
// 避免countDownLatch的值一直为0的情况
countDownLatch =null;
// 重新获取锁
lock();
}
//释放锁
public void unlock(){
if(zkClient !=null){
zkClient.close();
System.out.println(Thread.currentThread().getName()+",释放锁");
}
}
}
4、Test.java
public class Test {
public static void main(String[] args) {
for (int i =0; i <100; i++) {
new Thread(new OrderService()).start();
}
}
}