@[TOC] 用Java编写的一个简单示例代码,演示如何使用Zookeeper实现分布式锁
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class DistributedLock implements Watcher {
private static final String ZOOKEEPER_HOST = "localhost:2181";
private static final int SESSION_TIMEOUT = 5000;
private static final String LOCK_PATH = "/distributed_lock";
private ZooKeeper zooKeeper;
private CountDownLatch lockAcquiredSignal;
private String currentLockPath;
public DistributedLock() {
try {
zooKeeper = new ZooKeeper(ZOOKEEPER_HOST, SESSION_TIMEOUT, this);
lockAcquiredSignal = new CountDownLatch(1);
} catch (Exception e) {
e.printStackTrace();
}
}
public void lock() {
try {
// 创建临时顺序节点
currentLockPath = zooKeeper.create(LOCK_PATH + "/", null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
// 尝试获取锁
attemptLock();
lockAcquiredSignal.await();
} catch (Exception e) {
e.printStackTrace();
}
}
public void unlock() {
try {
// 删除临时节点释放锁
zooKeeper.delete(currentLockPath, -1);
zooKeeper.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private void attemptLock() throws KeeperException, InterruptedException {
List<String> children = zooKeeper.getChildren(LOCK_PATH, false);
Collections.sort(children);
int currentIndex = children.indexOf(currentLockPath.substring(LOCK_PATH.length() + 1));
if (currentIndex == 0) {
// 当前节点是最小节点,获取锁成功
lockAcquiredSignal.countDown();
} else {
// 监听前一个节点
String previousNodePath = LOCK_PATH + "/" + children.get(currentIndex - 1);
Stat stat = zooKeeper.exists(previousNodePath, true);
if (stat != null) {
lockAcquiredSignal.await();
} else {
attemptLock();
}
}
}
@Override
public void process(WatchedEvent event) {
if (event.getType() == Event.EventType.NodeDeleted) {
lockAcquiredSignal.countDown();
}
}
public static void main(String[] args) {
DistributedLock lock = new DistributedLock();
// 模拟多个线程竞争锁
for (int i = 1; i <= 5; i++) {
final int taskId = i;
new Thread(() -> {
try {
lock.lock();
System.out.println("Task " + taskId + " acquired the lock");
Thread.sleep(2000);
System.out.println("Task " + taskId + " completed");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}).start();
}
}
}