【发布时间】:2017-07-03 10:22:26
【问题描述】:
我需要构建一个队列,默认情况下将按时间顺序添加和删除元素。但是,如果客户端为队列设置了优先级标志,我需要能够根据元素的优先级顺序拉取元素。
我正在考虑创建一个由映射支持的优先级队列,该映射按优先级顺序跟踪队列索引,并且基于优先级标志,我可以从映射中提取项目并从队列中的索引中弹出项目。
但是,使用这种方法,问题是,天气我默认创建地图或仅在设置标志的情况下创建地图(考虑到动态创建地图的成本很高,我倾向于默认使用它)。
如果有更好的方法或者是否存在现有的实现,请告诉我。
这是我目前拥有的:
import javax.naming.OperationNotSupportedException;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class DynamicPriorityQueue<ComparableQueueElement> implements IQueue<ComparableQueueElement> {
private static final int CONSTANT_HUNDRED = 100;
private boolean fetchByCustomPriority = false;
private final ReentrantLock lock;
private final PriorityQueue<ComparableQueueElement> queue;
private final PriorityQueue<ComparableQueueElement> customPriorityQueue;
public DynamicPriorityQueue() {
this(null);
}
public DynamicPriorityQueue(Comparator<ComparableQueueElement> comparator) {
this.lock = new ReentrantLock();
this.queue = new PriorityQueue<>(CONSTANT_HUNDRED);
if (comparator != null)
this.customPriorityQueue = new PriorityQueue<ComparableQueueElement>(CONSTANT_HUNDRED, comparator);
else
this.customPriorityQueue = null;
}
public void setFetchByCustomPriority(boolean fetchByCustomPriority) throws OperationNotSupportedException {
if (this.customPriorityQueue == null)
throw new OperationNotSupportedException("Object was created without a custom comparator.");
this.fetchByCustomPriority = fetchByCustomPriority;
}
public void push(ComparableQueueElement t) throws InterruptedException {
if (this.lock.tryLock(CONSTANT_HUNDRED, TimeUnit.MILLISECONDS)) {
try {
this.queue.offer(t);
if (this.customPriorityQueue != null)
this.customPriorityQueue.offer(t);
} finally {
this.lock.unlock();
}
}
}
public ComparableQueueElement peek() {
return this.fetchByCustomPriority ? this.queue.peek()
: (this.customPriorityQueue != null ? this.customPriorityQueue.peek() : null);
}
public ComparableQueueElement pop() throws InterruptedException {
ComparableQueueElement returnElement = null;
if (this.lock.tryLock(CONSTANT_HUNDRED, TimeUnit.MILLISECONDS)) {
try {
if (this.fetchByCustomPriority && this.customPriorityQueue != null) {
returnElement = this.customPriorityQueue.poll();
this.queue.remove(returnElement);
}
else {
returnElement = this.queue.poll();
if (this.customPriorityQueue != null) {
this.customPriorityQueue.remove(returnElement);
}
}
} finally {
this.lock.unlock();
}
}
return returnElement;
}
}
【问题讨论】:
-
谢谢你。但是我的问题是,如果设计是最优的,还是我会继续使用另一种数据结构/方法?
-
如果优先级队列中的所有项目都具有相同的优先级,则队列推送/弹出应该非常有效,在 O(1) 时间内。
-
您是否需要一个容器,消费者可以从中选择是按优先顺序删除下一个元素还是按 FIFO 顺序删除下一个元素?
-
如果您的项目队列不是很大,只需根据客户的偏好重新排列队列即可。也就是说,使用不同的排序比较函数创建一个新队列。此偏好多久更改一次,您的队列中有多少项目?
标签: java multithreading data-structures priority-queue