2

我有一个 scala 演员,只要客户请求它,它就会做一些工作。当且仅当没有客户端处于活动状态时,我希望 Actor 进行一些后台处理。

最简单的方法是什么?我可以想到两种方法:

  1. 生成一个超时的新线程并定期唤醒actor。一种直接的方法,但我想避免创建另一个线程(以避免额外的代码、复杂性和开销)。

  2. Actor 类有一个 reactWithin 方法,可用于从 Actor 本身超时。但是文档说该方法不会返回。所以,我不确定如何使用它。

编辑; 澄清:

假设后台任务可以分解成可以独立处理的更小的单元。

4

3 回答 3

6

好的,我知道我需要投入 2 美分。根据作者的回答,我猜“优先接收”技术正是这里所需要的。可以在“ Erlang: priority receive question here at SO ”中找到讨论。这个想法是首先接受高优先级的消息,并且仅在没有高优先级的消息时才接受其他消息。

由于 Scala Actor 与 Erlang 非常相似,因此实现它的简单代码如下所示:

def act = loop {
  reactWithin(0) {
    case msg: HighPriorityMessage => // process msg
    case TIMEOUT =>
      react {
        case msg: HighPriorityMessage => // process msg
        case msg: LowPriorityMessage => // process msg
      }
  }
}

这工作如下。演员有一个带有消息的邮箱(队列)。( receiveor receiveWithin) 参数是一个偏函数,Actor 库在邮箱中查找可应用于此偏函数的消息。在我们的例子中,它只是一个对象HighPriorityMessage。因此,如果 Actor 库找到这样的消息,它会应用我们的部分函数并且我们正在处理高优先级的消息。否则,reactWithin使用超时 0 调用带有参数的部分函数,TIMEOUT​​我们立即尝试处理队列中任何可能的消息(因为它等待消息,我们无法排除获取的可能性HighPriorityMessage)。

于 2009-10-14T08:45:13.210 回答
2

听起来您描述的问题不太适合演员子系统。AnActor旨在按顺序处理其消息队列:

  • 如果演员正在执行后台工作并且有新任务到达,会发生什么?

演员只能发现mailbox它在执行后台任务时不断检查它。您将如何实现这一点(即,您如何将后台任务编码为一个工作单元,以便参与者可以继续打断和检查邮箱)?

  • 如果actor在主任务前面的邮箱中有很多后台任务,应该怎么办?

这些后台任务会被丢弃,还是发送给其他参与者?如果是后者,您如何防止 CPU 时间分配给该参与者来执行任务?

总而言之,这听起来更像是你需要探索一些可以在后台运行的网格式软件(比如 Data Synapse)!

于 2009-10-13T14:20:50.440 回答
2

就在问了这个问题之后,我尝试了一些完全古怪的代码,它似乎工作正常。我不确定其中是否有问题。

import scala.actors._

object Idling

object Processor extends Actor {
  start

  import Actor._

  def act() = {
    loop {

      // here lie dragons >>>>>
      if (mailboxSize == 0) this ! Idling
      // <<<<<<

      react {
        case msg:NormalMsg => {
          // do the normal work
          reply(answer)
        }

        case Idling=> {
          // do the idle work in chunks
        }

        case msg => println("Rcvd unknown message:" + msg)
      }

    }
  }
}

解释

当 Actor 即将等待消息时,似乎loop在调用 to 之前的参数中的任何代码都会被调用。react我在Idling这里给自己发信息。在此消息的处理程序中,我确保邮箱大小为 0,然后再进行处理。

于 2009-10-13T14:41:23.853 回答