【问题标题】:Easiest way to do idle processing in a Scala Actor?在 Scala Actor 中进行空闲处理的最简单方法是什么?
【发布时间】:2009-10-14 16:45:13
【问题描述】:

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

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

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

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

编辑;澄清:

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

【问题讨论】:

    标签: scala actor


    【解决方案1】:

    好的,我知道我需要投入 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
          }
      }
    }
    

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

    【讨论】:

    • 虽然我的解决方案在实践中有效,但我认为这更惯用,因此接受它。我最初想使用 reactWithin 但在 TIMEOUT 上没有找到任何文档
    【解决方案2】:

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

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

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

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

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

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

    【讨论】:

    • 我理解您的担忧。但重要的是,我要运行的后台任务必须在演员不做任何事情时完成。回答你的问题: 1.后台任务可以分解成更小的单元。如果参与者在处理正常请求之前完成了它当前正在执行的后台工作单元,那就没问题了。 2. 希望使用 Actor.mailboxSize 在其他人在队列中等待时忽略后台任务。
    【解决方案3】:

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

    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,然后再进行处理。

    【讨论】:

    • 唯一可行的方法是通过消息向这个actor发送空闲任务。否则,任何空闲任务都会导致邮箱中只有一个项目
    • @oxbow_lakes 不确定我理解。此代码在实践中有效,我正在通过消息发送空闲任务。
    • 根据您自己的回答,我可以建议您发明“优先接收”(源自 Erlang,但可以使用 Scala 演员实现)
    • @HRJ - 如果mailbox 为空,actor 的消息队列中怎么会有空闲任务?肯定是演员从其他地方获取空闲任务的情况......
    猜你喜欢
    • 1970-01-01
    • 2018-12-19
    • 1970-01-01
    • 2012-05-02
    • 1970-01-01
    • 2012-06-20
    • 1970-01-01
    • 2019-04-20
    • 2012-03-13
    相关资源
    最近更新 更多