1. 分布式锁
创建临时节点实现分布式锁,实现的是独占锁。
public interface Lock {
void lock();
void unlock();
}
public abstract class ZkAbstractLock implements Lock {
private static String connectStr = "192.168.67.139:2184";
public static String path = "/lock";
protected ZkClient client = new ZkClient(connectStr);
@Override
public void lock() {
if (tryLock()) {
System.out.println(Thread.currentThread().getName() + "--->获取锁成功!");
} else {
waitForLock();
lock();
}
}
protected abstract boolean tryLock();
protected abstract void waitForLock();
@Override
public void unlock() {
client.close();
}
}
public class ZkLockImpl extends ZkAbstractLock {
private CountDownLatch cdl = null;
@Override
protected boolean tryLock() {
try {
client.createEphemeral(path);
return true;
} catch (ZkException e) {
return false;
}
}
@Override
protected void waitForLock() {
IZkDataListener iZkDataListener = new IZkDataListener() {
@Override
public void handleDataChange(String dataPath, Object data) {
}
//一旦/lock节点被删除以后,就会触发这个方法
@Override
public void handleDataDeleted(String dataPath) {
//让等待的代码不再等待了
if (cdl != null) {
cdl.countDown();
}
}
};
//注册 Watcher
client.subscribeDataChanges(path, iZkDataListener);
if (client.exists(path)) {
cdl = new CountDownLatch(1);
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//取消该客户端的订阅关系
client.unsubscribeDataChanges(path, iZkDataListener);
}
}
2. 分布式栅栏
public class BarrierDemo {
private static String barrierPath = "/barrier";
ZkClient zkClient = new ZkClient("192.168.67.139:2184");
@Test
public void test() throws InterruptedException {
//核心思想是每个任务执行完成后,在节点上创建一个子节点,当子节点个数达到要求后,放行下一个任务
init();
for (int i = 0; i < 10; i++) {
task("task" + i, new Random().nextInt(20));
}
monitor();
Thread.currentThread().join();
}
private void init() {
if (!zkClient.exists(barrierPath)) {
zkClient.createPersistent(barrierPath, 10);
}
listener();
}
private void task(String nodeName, int loop) {
CompletableFuture.runAsync(() -> {
for (int i = 0; i < loop; i++) {
System.out.println(nodeName + "-->" + (loop - i));
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("=========" + nodeName + "========任务完成,开始创建临时有序节点");
zkClient.createEphemeralSequential(barrierPath + "/" + nodeName, "");
});
}
private void monitor() throws InterruptedException {
Integer nodeNum = zkClient.readData(barrierPath);
while (true) {
List<String> children = zkClient.getChildren(barrierPath);
if (nodeNum == children.size()) {
zkClient.createEphemeral(barrierPath + "/start", "");
break;
}
TimeUnit.MILLISECONDS.sleep(100);
}
}
private void listener() {
zkClient.subscribeChildChanges(barrierPath + "/start", ((parentPath, currentChilds) -> {
if (parentPath.equals(barrierPath + "/start")) {
System.out.println("===========全部任务做完了=========");
System.exit(1);
}
}));
}
}
3. 分布式队列
public class FIFOQueue<T> {
protected final ZkClient zkClient;
protected final String root;
protected static final String node_name = "n_";
public FIFOQueue(ZkClient zkClient, String root) {
this.root = root;
this.zkClient = zkClient;
}
private int size() {
return zkClient.getChildren(root).size();
}
private boolean isEmpty() {
return zkClient.getChildren(root).size() == 0;
}
public boolean push(T data) {
String nodePath = root.concat("/").concat(node_name);
try {
zkClient.createEphemeralSequential(nodePath, data);
System.out.println(Thread.currentThread().getName() + "--> 成功push数据!!");
} catch (ZkNoNodeException e) {
zkClient.createPersistent(root);
push(data);
} catch (Exception e) {
throw ExceptionUtil.convertToRuntimeException(e);
}
return true;
}
public T poll() {
List<String> children = zkClient.getChildren(root);
if (children.size() == 0) {
return null;
}
Collections.sort(children, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return getNodeNumber(o1, node_name).compareTo(getNodeNumber(o2, node_name));
}
});
try {
String pollData = children.get(0);
String fullPath = root.concat("/").concat(pollData);
T data = (T) zkClient.readData(fullPath);
zkClient.delete(fullPath);
return data;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private String getNodeNumber(String string, String nodeName) {
int index = string.lastIndexOf(nodeName);
if (index >= 0) {
index += node_name.length();
return index <= string.length() ? string.substring(index) : "";
}
return string;
}
}
4. 分布式 ID
public class Id {
private static String connectStr = "192.168.67.139:2184";
private final String root = "/ID";
private final String nodeName = "/order";
private ZkClient zkClient = null;
private ExecutorService delExector = null;
public Id() {
init();
}
private void init() {
zkClient = new ZkClient(connectStr, 5000);
delExector = Executors.newFixedThreadPool(10);
if (!zkClient.exists(root)) {
zkClient.createPersistent(root);
}
}
private String getId() {
String nodePath = root.concat(nodeName);
String ephemeralSequential = zkClient.createEphemeralSequential(nodePath, "");
System.out.println(ephemeralSequential);
delExector.execute(() -> zkClient.delete(ephemeralSequential));
return getId(ephemeralSequential);
}
private void stop() {
delExector.shutdown();
try {
delExector.awaitTermination(2, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (zkClient != null) {
zkClient.close();
}
}
private String getId(String str) {
int index = str.lastIndexOf(nodeName);
return str.substring(index + nodeName.length());
}
public static void main(String[] args) {
Id id = new Id();
System.out.println(id.getId());
id.stop();
}
}