睡觉的演员?

Joe*_*Joe 16 scala actor

让演员入睡最好的方法是什么?我将演员设置为代理,希望维护数据库的不同部分(包括从外部源获取数据).由于多种原因(包括没有超载数据库或通信和一般负载问题),我希望演员在每个操作之间休眠.我正在看10个演员对象.

演员将无限运行,因为总会有新数据进入,或者坐在表中等待传播到数据库的其他部分等.想法是让数据库在任何时候都尽可能完整及时.

我可以通过无限循环执行此操作,并在每个循环结束时进行休眠,但根据http://www.scala-lang.org/node/242,actor使用线程池,只要所有线程都被阻塞,它就会被扩展.所以我想每个actor中的Thread.sleep都是个坏主意,因为会不必要地浪费线程.

我可能有一个中央演员有自己的循环,在时钟上发送消息给订阅者(如异步事件时钟观察者)?

有没有人做过类似的事情或有任何建议?很抱歉有额外的(可能是多余的)信息.

干杯

Ale*_*rov 21

在第一个答案中,Erlang有一个很好的观点,但它似乎消失了.您可以轻松地使用Scala actor执行与Erlang类似的技巧.例如,让我们创建一个不使用线程的调度程序:

import actors.{Actor,TIMEOUT}

def scheduler(time: Long)(f: => Unit) = {
  def fixedRateLoop {
    Actor.reactWithin(time) {
      case TIMEOUT => f; fixedRateLoop
      case 'stop => 
    }
  }
  Actor.actor(fixedRateLoop)
}
Run Code Online (Sandbox Code Playgroud)

让我们使用测试客户端actor测试它(我在Scala REPL中做得很好):

case class Ping(t: Long)

import Actor._
val test = actor { loop {
  receiveWithin(3000) {
    case Ping(t) => println(t/1000)
    case TIMEOUT => println("TIMEOUT")
    case 'stop => exit
  }
} }
Run Code Online (Sandbox Code Playgroud)

运行调度程序:

import compat.Platform.currentTime
val sched = scheduler(2000) { test ! Ping(currentTime) }
Run Code Online (Sandbox Code Playgroud)

你会看到这样的东西

scala> 1249383399
1249383401
1249383403
1249383405
1249383407
Run Code Online (Sandbox Code Playgroud)

这意味着我们的调度程序按预期每2秒发送一条消息.我们停止调度程序:

sched ! 'stop
Run Code Online (Sandbox Code Playgroud)

测试客户端将开始报告超时:

scala> TIMEOUT
TIMEOUT
TIMEOUT
Run Code Online (Sandbox Code Playgroud)

也停止它:

test ! 'stop
Run Code Online (Sandbox Code Playgroud)

  • +1用于显示导入并具有REPL可运行的示例. (2认同)

oxb*_*kes 17

没有必要明确地让一个actor睡觉:对每个actor 使用loopreact表示底层线程池将有等待线程,而没有消息供actor处理.

如果您要为要处理的actor 调度事件,使用java.util.concurrent实用程序中的单线程调度程序非常容易:

object Scheduler {
  import java.util.concurrent.Executors
  import scala.compat.Platform
  import java.util.concurrent.TimeUnit
  private lazy val sched = Executors.newSingleThreadScheduledExecutor();
  def schedule(f: => Unit, time: Long) {
    sched.schedule(new Runnable {
      def run = f
    }, time , TimeUnit.MILLISECONDS);
  }
}
Run Code Online (Sandbox Code Playgroud)

您可以对此进行扩展以执行定期任务,因此可以使用它:

val execTime = //...  
Scheduler.schedule( { Actor.actor { target ! message }; () }, execTime)
Run Code Online (Sandbox Code Playgroud)

然后,您的目标actor将只需要实现一个适当的react循环来处理给定的消息.你没有必要让任何演员入睡.