在Scala Actor中进行空闲处理的最简单方法是什么?

时间:2009-10-13 13:54:14

标签: scala actor

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

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

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

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

  3. 修改;澄清:

    假设后台任务可以分解为可以独立处理的较小单位。

3 个答案:

答案 0 :(得分: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
      }
  }
}

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

答案 1 :(得分:2)

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

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

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

  • 如果演员在主要任务前面的邮箱中有很多后台任务会怎么样?

这些后台任务会被丢弃,还是被发送给另一个演员?如果是后者,你怎么能阻止给那个演员执行任务的CPU时间?

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

答案 2 :(得分: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)
      }

    }
  }
}

<强>解释

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