【问题标题】:Scala :: PriorityQueue => update priority of specific itemScala :: PriorityQueue => 更新特定项目的优先级
【发布时间】:2012-08-28 10:09:39
【问题描述】:

我已经实现了从头部提取项目的例程,更新它的优先级并使用这样的非阻塞方法将其放回队列(使用 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)
}

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

Change priority of items in a priority queue有关

【问题讨论】:

  • 您是否尝试过使用不同的方法:例如SortedSet(或SortedMap)?
  • @oxbow_lakes 现在我正在尝试用 TreeSet 实现它
  • 你没有定义上面的load是什么。

标签: scala nonblocking priority-queue


【解决方案1】:

使用不可变的树形图 (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() 后将其添加回来.代码几乎一样。

【讨论】:

    猜你喜欢
    • 2020-08-09
    • 2010-12-24
    • 1970-01-01
    • 2015-05-23
    • 2012-02-24
    • 1970-01-01
    • 2012-06-15
    相关资源
    最近更新 更多