将迭代器上的Scala并发作为队列

时间:2012-12-11 14:53:37

标签: scala parallel-processing

我不确定问题的正确用语,所以请随时向我提供正确的用语。

假设我有一个进程A,它输出一个迭代器(延迟评估) 这产生了迭代器[A]

然后我有另一个进程B,它映射返回的事件 迭代器[B]

这将继续进行多个流程 迭代器[A] - >迭代器[B] - >迭代器[C] - > ---

现在我最终将此流评估为列表[Z]。 这节省了我有一个List [A] - >的内存命中列表[B] - >列出[C]等

现在我想通过引入并行化来提高性能,但我不希望跨迭代器对每个元素的评估进行并行化,而是每个迭代器堆栈。因此,在这种情况下,进程A的线程为Iterator [A]填充队列[A],进程B的线程从队列[A]获取,应用任何映射,然后添加到队列[B]用于迭代器[B]阅读。

现在我已经通过设计自己的异步队列在其他语言中完成了这个,我想知道Scala要解决这个问题。

2 个答案:

答案 0 :(得分:1)

这是我使用演员制作的第一个解决方案。 它完全阻塞,所以也许可以开发使用期货的实现

case class AsyncIterator[T](iterator:Iterator[T]) extends Iterator[T] {
  private val queue = new scala.collection.mutable.SynchronizedQueue[Int]()
  private var end = !iterator.hasNext

  def hasNext() = {
    if (end) false
    else if (!queue.isEmpty) true
    else hasNext
  }

  def next() = {
    while (q.isEmpty) {
      if (end) throw new Exception("blah")
    }
    q.dequeue()
  }

  private val producer: Actor = actor {
    loop {
      if (!iterator.hasNext) {
        end = true
        exit
      }
      else {
        q.enqueue(iterator.next)
      }
    }
  }
  producer.start()
}

答案 1 :(得分:-3)

由于您对其他语言持开放态度,Go怎么样?

最近有a discussion关于如何构建一个事件驱动的管道,它可以实现与你描述的相同的东西,但是以完全不同的方式。

考虑和设计一个事件管道比讨论延迟迭代器更容易,因为它成为一个数据流系统,其中每个阶段的关键问题是“这个阶段对单一做什么实体?'而不是'我怎样才能在许多实体上有效地迭代?'

一旦实现了事件驱动的管道,如何使其并发或并行的问题没有实际意义 - 你已经完成了它。