Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在scala中实现生产者-消费者的正确方法是什么_Scala_Akka_Actor_Producer Consumer - Fatal编程技术网

在scala中实现生产者-消费者的正确方法是什么

在scala中实现生产者-消费者的正确方法是什么,scala,akka,actor,producer-consumer,Scala,Akka,Actor,Producer Consumer,我尝试在scala中实现生产者-消费者程序,而不使用队列。因为我认为Actor已经实现了“邮件队列”或其他东西,所以再次编写代码是多余的 我试图用纯演员的语言写这个节目。 下面是一个多制作人多消费者节目。 制作人为了模拟做某事而睡一会儿。消费者根本不睡觉 但是,如果我没有添加一个监控参与者来监控使用者,以及一个使用“wait”(代码中的监控类)的承诺对象,我不知道如何关闭程序 有没有办法摆脱它们 import akka.actor.Actor.Receive import akka.actor.

我尝试在scala中实现生产者-消费者程序,而不使用队列。因为我认为Actor已经实现了“邮件队列”或其他东西,所以再次编写代码是多余的

我试图用纯演员的语言写这个节目。 下面是一个多制作人多消费者节目。 制作人为了模拟做某事而睡一会儿。消费者根本不睡觉

但是,如果我没有添加一个监控参与者来监控使用者,以及一个使用“wait”(代码中的监控类)的承诺对象,我不知道如何关闭程序

有没有办法摆脱它们

import akka.actor.Actor.Receive
import akka.actor._
import akka.routing._;
import akka.util._

import scala.concurrent.{Await, Promise}
import scala.concurrent.duration._

class Producer(val pool:ActorRef)(val name:String) extends Actor {

  def receive = {
    case _ =>
      while (true) {
        val sleepTime = scala.util.Random.nextInt(1000)
        Thread.sleep(sleepTime)
        println("Producer %s send food" format name)
        pool ! name
      }
  }
}

class Consumer(supervisor : ActorRef)(val name:String) extends Actor {

  var counter = 0

  def receive = {
    case s => 
      counter += 1
      println("%s eat food produced by %s" format (name,s))

      if (counter >= 10) {
        println("%s is full" format name)

        context.stop(self)
        supervisor ! 1
      }
  }
}

class Supervisor(p:Promise[String]) extends Actor {

  var r = 3

  def receive = {
    case _ =>
      r -= 1
      if (0 == r) {
        println("All consumer stopped")
        context.stop(self)
        p success ("Good")
      }
  }

}

object Try3 {

  def work(): Unit = {
    val system = ActorSystem("sys1")
    val nProducer = 5;
    val nConsumer = 3;
    val p = Promise[String]
    val supervisor = system.actorOf(Props(new Supervisor(p)));
    val arrConsumer = for ( i <-  1 to nConsumer) yield system.actorOf( Props( new Consumer(supervisor)( "Consumer %d" format (i) ) ) )
    val poolConsumer = system.actorOf(Props.empty.withRouter( RoundRobinRouter(arrConsumer) ))
    val arrProducer = for ( i <-  1 to nProducer) yield system.actorOf( Props( new Producer(poolConsumer)( "Producer %d" format (i) ) ) )

    arrProducer foreach (_ ! "start")

    Await.result(p.future,Duration.Inf)
    println("great!")
    system.shutdown
  }

  def main(args:Array[String]): Unit = {
    work()
  }
}
无论我的实现如何,在scala中使用Actor或Future/Promise实现生产者-消费者程序的正确方法是什么?

您永远不应该在Actor中阻塞(在您的情况下是Thread.sleep,while loop)。参与者内部的阻塞占用了所有参与者之间使用的线程池中的一个线程。即使是像您这样的少量制作人也会使actor系统中的所有参与者失去线程,并使其无法使用

而是使用
调度程序
在制作人中定期安排meesage发送

覆盖def preStart():单位={
导入scala.concurrent.duration_
导入context.dispatcher
context.system.scheduler.schedule(
初始延迟=0.5秒,
间隔=1.5秒,
接收器=池,
消息=名称
)
}

您认为如何实现
终止符
Actor:)


谢谢你,Martynas。你解决了我的“循环”问题。我仍然在为生产者消费者的优雅实现寻找答案。
class Producer(val pool:ActorRef)(val name:String) extends Actor {

  //  original implementation:
  //  def receive = {
  //    case _ =>
  //    while (true){
  //      val sleepTime = scala.util.Random.nextInt(1000)
  //      Thread.sleep(sleepTime)
  //      println("Producer %s send food" format name)
  //      pool ! name
  //    }
  //  }

  case object Loop;

  def receive = {
    case _ =>
      val sleepTime = scala.util.Random.nextInt(1000)
      Thread.sleep(sleepTime)
      println("Producer %s send food" format name)
      pool ! name
      self ! Loop   //send message to itself
  }
}
object Terminator {
  case class WatchMe(ref: ActorRef)
}
class Terminator extends Actor { 
   var consumers: Map[ActorRef, ActorRef] = Map()

   def receive = { 
      case WatchMe(ref) => {
        consumers += ref -> ref
        context.watch(ref)
      }
      case Terminated(ref) => {
         context.unwatch(ref)
         consumers.get(ref).foreach { ref -> ref ! PoisonPill } 
         consumers -= ref
         //If all consumers are dead stop.self and delegate NoConsumers message higher in hierarchy
         if(consumers.size == 0) { 
           delegate()
           context.stop(self)
         }
      }
   }
}