Scala :: PriorityQueue =>更新特定项目的优先级

时间:2012-08-28 10:09:39

标签: scala nonblocking priority-queue

我已经实现了从头部提取项目的例程,更新它的优先级并使用非阻塞方法将其放回队列(使用AtomicReference)

def head(): Entry = {
  def takeAndUpdate(e: Entry, success: Boolean): Entry = {
    if (success) {
      return e
    }
    val oldQueue = queueReference.get()
    val newQueue = oldQueue.clone()
    val item = newQueue.dequeue().increase()
    newQueue += item
    takeAndUpdate(item.e, queueReference.compareAndSet(oldQueue, newQueue))
  }
  takeAndUpdate(null, false)
}

现在我需要找出队列中的任意Entry,更改它的优先级并将其放回队列。似乎PriorityQueue不支持这个,所以我应该使用哪个类来实现所需的行为?

这与Change priority of items in a priority queue

有关

1 个答案:

答案 0 :(得分:2)

使用不可变树图(immutable.TreeMap)来完成此任务。您必须以某种方式找到您想要的条目 - 最好的方法是将您使用的信息部分(Key)与要查找带有密钥的条目以及您希望返回的实际条目相关联地图中的值(调用此Entry)。

使用queueReference重命名treeReference。在您创建集合的代码部分中,使用immutable.TreeMap[Key, Entry](<list of elements>)

然后像这样修改代码:

def updateKey(k: Key) {
  @annotation.tailrec def update(): (Key, Entry) = {
    val oldTree = treeReference.get()
    val entry = oldTree(k)
    val newPair = modifyHoweverYouWish(k, entry)
    val newTree = (oldTree - k) + newPair
    if (treeReference.compareAndSet(oldTree, newTree)) newPair
    else update()
  }
  update()
}

如果compareAndSet失败,您必须像在资源中那样重复。最好使用@tailrec,如上所示,以确保函数是尾递归并防止潜在的堆栈溢出。

或者,您可以使用immutable.TreeSet - 如果您知道对Entry对象的确切引用,则可以使用它来通过-删除元素,然后添加它在致电increase()后回来。代码几乎相同。