在Scala的内存队列中实现哪些支持poll(n)功能的正确方法是什么?

时间:2015-07-30 11:47:14

标签: scala queue

在Scala的内存线程安全队列中实现哪些支持poll(n)功能的正确方法是什么?所以我可以给一个数字,并得到队列的子集。返回的所有元素也应从原始队列中删除。

Queue.splitAt(n)做了我需要的东西,但看起来非常低效,因为它只是遍历所有元素: https://github.com/scala/scala/blob/2.12.x/src/library/scala/collection/TraversableLike.scala

def splitAt(n: Int): (Repr, Repr) = {
  val l, r = newBuilder
  l.sizeHintBounded(n, this)
   if (n >= 0) r.sizeHint(this, -n)
   var i = 0
   for (x <- this) {
    (if (i < n) l else r) += x
    i += 1
  }
  (l.result, r.result)
}

1 个答案:

答案 0 :(得分:0)

只要您不介意对poll(n)的并发呼叫可能会交错其基础poll()来电,以下内容可能对您有用:

import java.util.Queue
import java.util.concurrent.ConcurrentLinkedQueue
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.concurrent.{Await, Future}

implicit class QueueExtensions[T](q: Queue[T]) {

  def poll(n: Int, acc: List[T] = List.empty): List[T] = n match {
    case 0 => acc
    case c =>
      val item = q.poll()
      if (item == null)//queue is empty
        acc
      else
        poll(n-1, acc :+ item)
  }
}

val queue = new ConcurrentLinkedQueue[Int]()
(1 to 10) foreach {queue.add(_)}
val f1 = Future(queue.poll(3))
val f2 = Future(queue.poll(4))
val output = for{
  l1 <- f1
  l2 <- f2
}yield{
  val s1 = l1.foldLeft("List 1:")((str, v) => str + " " + v)
  val s2 = l2.foldLeft(" List 2: ")((str, v) => str + " " + v) 
  s1 + "\n" + s2
}
println(Await.result(output, 3 seconds))

要了解交错的含义,您可能需要暂时将poll(n)编辑为:

def poll(n: Int, acc: List[T] = List.empty): List[T] = n match {
    case 0 => acc
    case c =>
      Thread.sleep(10)
      val item = q.poll()
      if (item == null)//queue is empty
        acc
      else
        poll(n-1, acc :+ item)
  }