1、pom文件中添加依赖
<dependencies>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
</dependencies>
2、定义接口获取锁、释放锁
public interface ExtLock {
//基于zk实现分布式锁
// 获取锁
public void getLock();
// 释放锁
public void unLock();
}
3、
public abstract class ZookeeperAbstractLock implements ExtLock {
// 集群连接地址
protected String CONNECTION = "127.0.0.1:2181";
// zk客户端连接
protected ZkClient zkClient = new ZkClient(CONNECTION);
// path路径
protected String lockPath = "/path";
protected CountDownLatch countDownLatch = new CountDownLatch(1);
public void getLock() {
if (tryLock()) {
System.out.println("####获取锁成功######");
} else {
waitLock();
getLock();
}
}
// 获取锁
abstract boolean tryLock();
// 等待锁
abstract void waitLock();
public void unLock() {
if (zkClient != null) {
System.out.println("#######释放锁#########");
zkClient.close();
}
}
}
4、实现 获取锁 等待锁
public class ZookeeperDistrbuteLock extends ZookeeperAbstractLock {
@Override
boolean tryLock() {
try {
zkClient.createEphemeral(lockPath);
return true;
} catch (Exception e) {
return false;
}
}
@Override
void waitLock() {
// 使用zk临时事件监听
IZkDataListener iZkDataListener = new IZkDataListener() {
public void handleDataDeleted(String path) throws Exception {
if (countDownLatch != null) {
countDownLatch.countDown();
}
}
public void handleDataChange(String arg0, Object arg1) throws Exception {
}
};
// 注册事件通知
zkClient.subscribeDataChanges(lockPath, iZkDataListener);
if (zkClient.exists(lockPath)) {
countDownLatch = new CountDownLatch(1);
try {
countDownLatch.await();
} catch (Exception e) {
// TODO: handle exception
}
}
// 监听完毕后,移除事件通知
zkClient.unsubscribeDataChanges(lockPath, iZkDataListener);
}
}
5、调用类
public class OrderNumGenerator {
// 生成订单号规则
private static int count = 0;
public String getNumber() {
try {
Thread.sleep(200);
} catch (Exception e) {
}
SimpleDateFormat simpt = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
return simpt.format(new Date()) + "-" + ++count;
}
}
public class OrderService implements Runnable {
private OrderNumGenerator orderNumGenerator = new OrderNumGenerator();
private ExtLock extLock = new ZookeeperDistrbuteLock();
public void run() {
getNumber();
}
public void getNumber() {
try {
extLock.getLock();
String number = orderNumGenerator.getNumber();
System.out.println("线程:" + Thread.currentThread().getName() + ",生成订单id:" + number);
} catch (Exception e) {
} finally {
extLock.unLock();
}
}
public static void main(String[] args) {
System.out.println("多线程生成number");
// OrderService orderService = new OrderService();
for (int i = 0; i < 100; i++) {
//创建多个连接,模拟分布式多线程调用
new Thread(new OrderService()).start();
}
}
}
调用main测试下就好,发现生产的 number 没有重复的
不要强制关闭控制台,会导致通知延迟。