4

我有一个函数重试,它基本上看起来像这样(简化):

object SomeObject {
 def retry[T](n: Int)(fn: => T): Option[T] = {
    val res = try {
      Some(fn)
    } catch {
      case _: Exception => None
    }

    res match {
      case Some(x) => Some(x)
      case None => 
        if (n > 1) 
          //make it sleep for a little while
          retry(n - 1)(fn) 
        else None
    }
  }
}

我需要在尝试之间稍作停顿。Thread.sleep(123)有人告诉我,在演员内部打电话是不可接受的:

class MyActor extends Actor {
  //......
  def someFunc = {
    Thread.sleep(456) // it's not acceptable in an actor, there is another way to do it
  }

}

显然,我不知道客户是否会SomeObject.retry在演员内部使用:

class MyActor extends Actor {
  //......
  def someFunc = {
    SomeObject.retry(5)(someRequestToServer) // ops, SomeObject.retry uses Thread.sleep!
  }

}

所以,如果我只是添加:

res match {
      case Some(x) => Some(x)
      case None => 
        if (n > 1) 
          //make it sleep for a little while
          Thread.sleep(123) // ops, what if it's being called inside an actor by a client?!
          retry(n - 1)(fn) 
        else None
    }
  }

这不会是明智的,不是吗?如果没有,我该怎么办?

4

1 回答 1

7

是的,调用Thread.sleep是一个坏主意,因为在 Actor 系统中,线程通常是 Actor 之间共享的有限资源。您不希望一个 Actor 调用 sleep 并从其他 Actor 中占用一个线程。

相反,您应该做的是使用Scheduler(请参阅文档)让您的演员在将来的某个时间向自己发送一条消息以重试。为此,您必须将重试代码移出SomeObject和移入Actor

class MyActor extends Actor {

  import context.system.dispatcher

  def receive = {
    case DoIt(retries) if retries > 0 => 
      SomeObject.attempt(someRequestToServer) match {
        case Some(x) => ...
        case None => 
          context.system.scheduler.scheduleOnce(5.seconds, self, DoIt(retries - 1))
      }
  }

}

然后,如果您在SomeObject.try演员系统之外使用

def attempt(retries: Int) = {
  SomeObject.attempt(someRequestToServer) match {
    case Some(x) => ...
    case None if retries > 0 => {
      Thread.sleep(123)
      attempt(retries - 1)
    }
  }
}

在哪里SomeObject.attempt

object SomeObject {
  def attempt[T](fn: => T): Option[T] =
    try {
      Some(fn)
    } catch {
      case _: Exception => None
    }
}
于 2013-11-09T17:33:54.940 回答