使用路径为/queue的znode下的节点表示队列中的元素。/queue下的节点都是顺序持久化的znode。这些znode名字的后缀数字表示了对应队列元素在队列中的位置。Znode名字后缀数字越小,对应队列元素在队列中的位置越靠前。
offer方法:
在/queue下面创建一个顺序znode。因为znode的后缀数字是/queue下面现有znode最大后缀数字加1,所有znode对应的队列元素处于队尾
/**
-
向队列提交数据
-
@param element 提交的数据
-
@return
-
@throws Exception
*/
public boolean offer(T element) throws Exception {
String nodeFullPath = root.concat(“/”).concat(Node_NAME);
try {
// 创建持久的顺序节点
zkClient.createPersistentSequential(nodeFullPath, element);
} catch (ZkNoNodeException e) {
zkClient.createPersistent(root);
offer(element);
} catch (Exception e) {
throw ExceptionUtil.convertToRuntimeException(e);
}
return true;
}
poll方法:
/**
-
从队列获取数据
-
@return
-
@throws Exception
*/
public T poll() throws Exception {
try {
List list = zkClient.getChildren(root);
if (list.size() == 0) {
return null;
}
// 排序队列 根据名称由小到大
Collections.sort(list, new Comparator() {
public int compare(String lhs, String rhs) {
return getNodeNumber(lhs, Node_NAME).compareTo(getNodeNumber(rhs, Node_NAME));
}
});
for (String nodeName : list) {
String nodeFullPath = root.concat(“/”).concat(nodeName);
try {
T node = (T) zkClient.readData(nodeFullPath);
zkClient.delete(nodeFullPath);
return node;
} catch (ZkNoNodeException e) {
// 其他客户端消费了 继续循环
}
}
return null;
} catch (Exception e) {
throw ExceptionUtil.convertToRuntimeException(e);
}
}
注意:T node = (T) zkClient.readData(nodeFullPath);的成功,并不代表删除的成功,原因是该队列元素可能会被其他的用户出队。
总体的代码:
package com.queue.model;
import java.io.Serializable;
public class User implements Serializable {
private static final long serialVersionUID = 7726840211952830151L;
String name;
String id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public String toString() {
return “User{” +
“name='” + name + ‘’’ +
“, id='” + id + ‘’’ +
‘}’;
}
}
package com.queue;
import org.I0Itec.zkclient.ExceptionUtil;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.exception.ZkNoNodeException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
-
简单的分布式队列
-
@author jerome_s@qq.com
-
@date 2016/8/30 20:19
*/
public class DistributedSimpleQueue {
protected final ZkClient zkClient;
/**
- 根节点路径
*/
protected final String root;
/**
- 顺序节点的前缀
*/
protected static final String Node_NAME = “qn_”;
public DistributedSimpleQueue(ZkClient zkClient, String root) {
this.zkClient = zkClient;
this.root = root;
}
/**
-
获取队列的大小
-
@return
*/
public int getQueueSize() {
return zkClient.getChildren(root).size();
}
/**
-
向队列提交数据
-
@param element 提交的数据
-
@return
-
@throws Exception
*/
public boolean offer(T element) throws Exception {
String nodeFullPath = root.concat(“/”).concat(Node_NAME);
try {
// 创建持久的顺序节点
zkClient.createPersistentSequential(nodeFullPath, element);
} catch (ZkNoNodeException e) {
zkClient.createPersistent(root);
offer(element);
} catch (Exception e) {
throw ExceptionUtil.convertToRuntimeException(e);
}
return true;
}
public List element() {
List list = zkClient.getChildren(root);
// 排序队列 根据名称由小到大
Collections.sort(list, new Comparator() {
public int compare(String lhs, String rhs) {
本次面试答案,以及收集到的大厂必问面试题分享:
ement);
} catch (Exception e) {
throw ExceptionUtil.convertToRuntimeException(e);
}
return true;
}
public List element() {
List list = zkClient.getChildren(root);
// 排序队列 根据名称由小到大
Collections.sort(list, new Comparator() {
public int compare(String lhs, String rhs) {
本次面试答案,以及收集到的大厂必问面试题分享:
[外链图片转存中…(img-123XpRzP-1714481859252)]