Scala 从线程模型到参与者的转换

Scala 从线程模型到参与者的转换,scala,concurrency,refactoring,actor,Scala,Concurrency,Refactoring,Actor,试图掌握如何从参与者而不是线程的角度来思考。我对以下用例有点困惑: 考虑一个系统,它有一个创建工作的生产者进程(例如,通过从文件中读取数据)和一系列使用工作的工作进程(例如,通过解析数据并将其写入数据库)。工作产生和消耗的速度可能会有所不同,系统应该对此保持稳健。例如,如果工人跟不上,生产商应该检测到这一点,并最终减速或等待 这很容易用线程实现: val producer:Iterator[Work] = createProducer() val queue = new LinkedBlocki

试图掌握如何从参与者而不是线程的角度来思考。我对以下用例有点困惑:

考虑一个系统,它有一个创建工作的生产者进程(例如,通过从文件中读取数据)和一系列使用工作的工作进程(例如,通过解析数据并将其写入数据库)。工作产生和消耗的速度可能会有所不同,系统应该对此保持稳健。例如,如果工人跟不上,生产商应该检测到这一点,并最终减速或等待

这很容易用线程实现:

val producer:Iterator[Work] = createProducer()
val queue = new LinkedBlockingQueue[Work](QUEUE_SIZE)
val workers = (0 until NUM_WORKERS) map { i =>
  new Thread() { 
    override def run() = {
      while (true) {
        try {
          // take next unit of work, waiting if necessary
          val work = queue.take()
          process(work)
        }
        catch {
          case e:InterruptedException => return
        }
      }
    }
  }
}

// start the workers
workers.foreach(_.start())

while (producer.hasNext) {
  val work = producer.next()
  // add new unit of work, waiting if necessary
  queue.put(work)
}

while (!queue.isEmpty) {
  // wait until queue is drained
  queue.wait()
}

// stop the workers
workers.foreach(_.interrupt())

这个模型没有什么问题,我以前也成功地使用过。此示例可能过于冗长,因为使用Executor或CompletionService将非常适合此任务。但我喜欢演员的抽象,并且认为在很多情况下更容易推理。有没有一种方法可以使用actor重写这个示例,特别是确保没有缓冲区溢出(例如,邮箱已满、邮件丢失等)?

因为actor“脱机”处理邮件(即,邮件的使用与其接收无关),所以很难看到如何精确模拟“生产者等待消费者赶上”

我能想到的唯一一件事是,消费者向制作人-演员请求作品(使用
回复
):

当然,这并不完美,因为制作人不“向前阅读”,只有在消费者准备好后才能获得作品。用法如下:

val prod = new Producer
(1 to NUM_ACTORS).map(new Consumer(prod)).foreach(_.start())
prod.start()

人力资源管理,这是我想到的一个解决方案。这可能足够了,但我担心的是,如果工人超过了制作人,那么工作缓冲区的缺乏会导致性能下降。@toluju-开始让每个消费者要求工作,让制作人接收这些消息,而不是对这些消息做出反应,并将它们放在队列中如果没有更多的工作要做,则使用ue。(然后,一旦有工作,它可以将其划分为队列中的项目。)
val prod = new Producer
(1 to NUM_ACTORS).map(new Consumer(prod)).foreach(_.start())
prod.start()