是否适合使用Futures和Promises进行延迟初始化?

时间:2013-11-04 03:00:11

标签: scala akka promise future

使用Futures和Promises进行延迟初始化是否合适,而不是使用Option var或一些可变变量?

您可以创建一个封装承诺的工厂类:

class IntFactory{
  val intPromise = Promise[Int]
  def create () : Future[Int] = intPromise.future
  def init (data : String) : Unit = intPromise success data.length
}

演员或其他类可以像这样使用它:

class MyActor(factory : IntFactory) extends Actor{
  val future_int = factory.create()

  def receive = {
    case (msg : String) => factory.init(msg) // Now the promise is fulfilled  
  }
}

做这样的事情有什么不对吗?以演员为例可能并不理想,因为我认为演员有更好的选择(成为或FSM)。我目前正在考虑将其与非演员类一起使用。某些实例变量在某些事件发生之前是无效的。我正在考虑这样做而不是使用var选项并将其设置为None。如果这很糟糕,还有什么其他选择?

修改

我想到了这可能更有用的情况。如果我有多个需要初始化的东西,并且在完成所有操作时我想要执行一些异步操作:

class MyActor(factory1 : IntFactory, factory2 : IntFactory) extends Actor{
  val future_int1 = factory1.create()
  val future_int2 = factory2.create()

  for{
    x <- future_int1
    y <- future_int2
  } // Do some stuff when both are complete

  def receive = {
    case "first" => factory1.init("first") 
    case "second" => factory2.init("second") 
  }
}

然后,每次我得到另一件时,我都不必检查哪些是无。

更多编辑:

我在原始问题中未指定的其他一些信息:

  1. 初始化对象所需的数据将异步进入。

  2. 初始化需要传递给init函数的数据。我编辑了我的示例代码,现在就是这种情况。

  3. 我没有使用Akka。我认为Akka将有助于拼凑一个简单的例子,并认为经验丰富的Akka人可以提供有用的反馈。

2 个答案:

答案 0 :(得分:2)

是的,这肯定是比使用可变变量(无论是否为Option)更好的方法。正如@PatrykĆwiek建议的那样,如果您可以随时初始化状态而不是等待外部事件而不需要异步执行,那么使用lazy val会更好。

答案 1 :(得分:0)

从你的IntFactory判断,你真的不需要data字符串(它没有在任何地方使用),所以我认为可以像这样重写基本情况:

class Foo {
  lazy val first = {
    Thread.sleep(2000) // Some computation, initialization etc.
    25
  }
  lazy val second = {
    Thread.sleep(1000) // Some computation, initialization etc.
    11
  }
  def receive(s : String) = s match {
    case "first" => first
    case "second" => second
    case _ => -1
  }
}

现在,让我们说你这样做:

val foo = new Foo()
println(foo.receive("first"))  // waiting for 2 seconds, initializing
println(foo.receive("first"))  // returns immediately
println(foo.receive("second")) // waiting for 1 second, initializing

现在firstsecond最多只能初始化一次

您无法将参数传递给lazy val,因此如果data字符串对初始化有些重要,那么您最好使用具有memoization(IMO)的工厂方法。