通过用zk创建临时节点的特性,实现分布式锁;
当前只有一个线程创建成功,然后close之后,该节点被删除;
其他线程可以再次争抢。
实现一个生成订单号,几个线程生成几个订单号,模仿多jvm对应多个线程
public class OrderNumCreateUtil {
private static int number = 0;
public String getOrderNumber(){
return "\t 生成订单号:" + (++ number);
}
}
public interface ZkLock {
public void zklock();
public void zkUnlock();
}
利用模板方法模式,把需要经常改的东西抽象出来,交给子类去实现
public abstract class ZkAbstractLock implements ZkLock{
public static final String ZKSERVER = "47.100.41.55:2181";
public static final int TIME_OUT = 45 * 1000;
ZkClient zkClient = new ZkClient(ZKSERVER, TIME_OUT);
protected String path = "/zklock0401";
protected CountDownLatch countDownLatch = null;
@Override
public void zklock() {
if(tryZkLock()){
System.out.println(Thread.currentThread().getName() + "\t 占用锁成功。");
}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() + "\t 释放锁成功。");
System.out.println();
System.out.println();
}
}
public class ZkDistributedLock extends ZkAbstractLock{
@Override
public void waitZkLock() {
//监听path,1,数据是否改变或删除
IZkDataListener iZkDataListener = new IZkDataListener() {
@Override
public void handleDataDeleted(String arg0) throws Exception {
if(countDownLatch != null){
countDownLatch.countDown();
}
}
@Override
public void handleDataChange(String arg0, Object arg1) throws Exception {
}
};
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;
}
}
}
public class OrderService {
private OrderNumCreateUtil orderNumCreateUtil = new OrderNumCreateUtil();
private ZkLock zklock = new ZkDistributedLock();
public void getOrderNum(){
zklock.zklock();
try {
System.out.println("获得编号:----->:" + orderNumCreateUtil.getOrderNumber());
} catch (Exception e) {
}finally{
zklock.zkUnlock();
}
}
}
public class Client {
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
new Thread(()->{
//模仿多jvm
new OrderService().getOrderNum();
},String.valueOf(i)).start();
}
}
}