在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)
}
答案 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)
}