手写zookeeper分布式锁,测试生成订单编号
1.生成订单编号工具类
/**
* TODO
*
* @author CSD
* @date 2021-09-09 13:51
* 订单编号工具类
*/
public class OrderNumCreateUtil {
private static int number = 0;
/**
* 生成订单编号
* @return
*/
public String getNumber(){
return String.valueOf(++number);
}
}
2.订单业务类
/**
* TODO
* 订单业务类
* @author CSD
* @date 2021-09-09 13:54
*/
public class OrderService {
private OrderNumCreateUtil orderNumCreateUtil = new OrderNumCreateUtil();
private ZkLock zkLock = new ZkDistributedLock();
public void getOrdNumber() {
zkLock.zklock();
try {
String number = orderNumCreateUtil.getNumber();
System.out.println("number = " + number);
}catch (Exception e){
e.printStackTrace();
}finally {
zkLock.zkUnlock();
}
}
}
3.zookeeper接口
/**
* TODO
*
* @author CSD
* @date 2021-09-09 14:05
*/
public interface ZkLock {
public void zklock();
public void zkUnlock();
}
4. 使用模板设计模式把共用的代码抽离父类
/**
* TODO
*
* @author CSD
* @date 2021-09-09 14:07
*/
public abstract class ZkAbstractTemplateLock implements ZkLock {
protected String path = "/zkLock";
protected CountDownLatch countDownLatch = null;
public static final String ZKSERVER = "172.22.83.153:2181";
public static final Integer TIME_OUT = 45 * 1000;
ZkClient zkClient = new ZkClient(ZKSERVER,TIME_OUT);
@Override
public void zklock() {
if(tryZkLock()){
System.out.println("线程"+Thread.currentThread().getName()+":获得锁\n");
}else{
waitZkLock();
zklock();
}
}
public abstract void waitZkLock();
public abstract boolean tryZkLock();
@Override
public void zkUnlock() {
if (zkClient != null){
zkClient.close();
}
System.out.println("线程"+Thread.currentThread().getName()+"释放锁\n\n");
}
}
5.zk分布式锁具体的实现类
/**
* TODO
*
* @author CSD
* @date 2021-09-09 14:22
*/
public class ZkDistributedLock extends ZkAbstractTemplateLock{
@Override
public void waitZkLock() {
IZkDataListener iZkDataListener = new IZkDataListener() {
@Override
public void handleDataChange(String dataPath, Object data) {
}
@Override
public void handleDataDeleted(String dataPath){
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);
}
@Override
public boolean tryZkLock() {
try {
zkClient.createEphemeral(path);
return true;
} catch (Exception e){
return false;
}
}
}
6.开启10个线程测试
/**
* TODO
*
* @author CSD
* @date 2021-09-09 13:57
*/
public class Client {
public static void main(String[] args) {
for (int i = 0; i < 50; i++) {
new Thread(()->{
new OrderService().getOrdNumber();
},String.valueOf(i)).start();
}
}
}
7.运行结果
线程6:获得锁
number = 1
线程6释放锁
线程1:获得锁
number = 2
线程1释放锁
线程5:获得锁
number = 3
线程5释放锁
线程8:获得锁
number = 4
线程8释放锁
线程2:获得锁
number = 5
线程2释放锁
线程4:获得锁
number = 6
线程4释放锁
线程0:获得锁
number = 7
线程0释放锁
线程7:获得锁
number = 8
线程7释放锁
线程3:获得锁
number = 9
线程3释放锁
线程9:获得锁
number = 10
线程9释放锁
8.所用的maven依赖
com.github.sgroschupf
zkclient
0.1