0

我有一个不断更新值的程序。我希望能够定期查询当前值的操作。在我的特定示例中,每次更新都可以视为一种改进,并且该过程最终将收敛到最终的最佳答案,但我想要/需要访问中间结果。循环执行的速度和收敛所需的时间很重要。

例如,考虑这个循环:

var current = 0
while(current < 100){
  current = current + 1
}

我希望能够在任何循环迭代中获得电流值。

使用 Actor 的解决方案是:

class UpdatingActor extends Actor{
  var current : Int = 0
  def receive = {
    case Update => {
      current = current + 1
      if (current < 100) self ! Update
    }
    case Query => sender ! current
  }
}

您可以使用 become 或 FSM 摆脱 var,但这个示例更清楚 IMO。

或者,一个参与者可以运行操作并将每次循环迭代的更新结果发送给另一个参与者,后者的唯一职责是更新值并响应有关它的查询。我对 Akka 中的“代理”了解不多,但这似乎是一个潜在的用例。

使用 Scala 有哪些更好/替代的方法?我不需要使用演员;这只是我想到的一种解决方案。

4

2 回答 2

1

您的基于演员的解决方案没问题。

每次更改后将中间结果发送给“结果提供者”actor 也是一个好主意,如果计算会长时间阻塞该actor,并且您希望确保始终可以获得中间结果。另一种选择是让实际的计算器演员成为收集最佳结果的演员的孩子。这样,事物从外部充当单个参与者,并且您将具有状态(当前最佳结果)的参与者与执行计算的参与者分开,这可能会失败。

代理将是一种介于非常低级别的@volatile/AtomicInteger 方法和Actor 之间的解决方案。代理是只能通过在其上运行转换来修改的东西(并且有一个转换队列),但它具有始终可以访问的当前状态。虽然它不是位置透明的。因此,如果您需要,请继续使用演员方法。

这是您如何使用代理解决此问题的方法。您有一个执行长时间运行计算的线程(由 Thread.sleep 模拟)和另一个仅定期打印出当前最佳结果的线程(也由 Thread.sleep 模拟)。

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.concurrent._
import akka.agent.Agent

object Main extends App {
  val agent = Agent(0)

  def computation() : Unit = {
    for(i<-0 until 100) {
      agent.send { current => 
        Thread.sleep(1000) // to simulate a long-running computation
        current + 1
      }
    }
  }

  def watch() : Unit = {
    while(true) {
      println("Current value is " + agent.get)
      Thread.sleep(1000)
    }
  }

  global.execute(new Runnable {
    def run() = computation
  })
  watch()
}

但总而言之,我认为基于参与者的解决方案会更好。例如,您可以在与结果跟踪不同的机器上进行计算。

于 2013-11-07T16:16:53.197 回答
0

问题的范围有点宽,但我会尝试:)

首先,您的示例非常好,我看不出摆脱var. 这就是 Actor 的用途:保护可变状态。

其次,根据您的描述,您根本不需要演员。

class UpdatingActor {
  private var current = 0
  def startCrazyJob() {
    while(current < 100){
      current = current + 1
    }
  }

  def soWhatsGoingOn: Int = current 
}

您只需要一个线程来调用startCrazyJob,另一个线程会定期调用soWhatsGoingOn

恕我直言,actor 方法更好,但由您决定是否值得为此用例导入 akka 库。

于 2013-11-07T14:02:37.993 回答