Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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
Multithreading 在Scala演员中整合自主和反应行为的最佳方式?_Multithreading_Scala_Asynchronous_Actor_Event Based Programming - Fatal编程技术网

Multithreading 在Scala演员中整合自主和反应行为的最佳方式?

Multithreading 在Scala演员中整合自主和反应行为的最佳方式?,multithreading,scala,asynchronous,actor,event-based-programming,Multithreading,Scala,Asynchronous,Actor,Event Based Programming,我是一名经验丰富的Java程序员,现在开始开发基于actor的Scala应用程序。在我目前正在开发的一个应用程序中,我必须处理一个发送方参与者的实现,该发送方参与者表现出自治和反应行为。场景如下(伪代码): 我的问题是:对于需要集成自治性和反应性(如上所述)的Scala参与者来说,哪种方式是表达自治行为的最佳方式? 换句话说,在上面的示例中,哪种方式/风格是编写发送方参与者代码的最佳方式/风格 我提出了一个解决方案(如下所述),但由于我不是scala大师(现在:),我想知道我所实现的是否可以在更

我是一名经验丰富的Java程序员,现在开始开发基于actor的Scala应用程序。在我目前正在开发的一个应用程序中,我必须处理一个发送方参与者的实现,该发送方参与者表现出自治和反应行为。场景如下(伪代码):

我的问题是:对于需要集成自治性和反应性(如上所述)的Scala参与者来说,哪种方式是表达自治行为的最佳方式?

换句话说,在上面的示例中,哪种方式/风格是编写发送方参与者代码的最佳方式/风格

我提出了一个解决方案(如下所述),但由于我不是scala大师(现在:),我想知道我所实现的是否可以在更好/更好的解决方案中得到改进

case object START
case object A
case object B
case object C
case object SENT_A
case object SENT_B
case object ACK_A
case object ACK_B
case object ACK_C
case object STOP

class Sender(stdout: Stdout) extends Actor {
    def act() {
        self!START
        while (true){
            receive {
                case START =>
                    stdout!?A
                    self!SENT_A
                case SENT_A =>
                    stdout!?B
                    self!SENT_B
                case SENT_B =>
                    stdout!?C
                    stdout!?STOP
                    exit()
                case STOP => {
                    Console.println("[Sender:]Received STOP, terminating")
                    stdout!?STOP
                    exit()
                }
            }
        }
    }
}

class Stdout() extends Actor {
    def act() { 
        while (true) {
            receive{
                case A =>
                    Console.println("[Stdout:]A")
                    reply(ACK_A)
                case B =>
                    Console.println("[Stdout:]B")
                    reply(ACK_B)
              case C =>
                    Console.println("[Stdout:]C")
                    reply(ACK_C)
                    exit()
              case STOP =>
                    Console.println("[Stdout:]Received STOP, terminating")
                    exit()
            }
        }
    }
}

class StopNotifier(sender: Sender) extends Actor {
    def act() {
        /*
         * The idea is that the StopNotifier should send a STOP message to the Sender
         * when a certain condition is met.
         * The sleep used here is just a semplification, since the detection of such
         * a condition is not relevant for the example.
         */

        Thread.sleep(200)
        Console.println("[StopNotifier:]Sending STOP to sender")
        sender ! STOP
        exit()
   }
}

object app extends Application {
    val stdout = new Stdout
    stdout.start
    val sender = new Sender(stdout)
    sender.start
    val stopNotifier = new StopNotifier(sender)
    stopNotifier.start
}
在我当前的实现中特别困扰我的是这样一个事实:为了能够对从StopNotifier接收到的STOP消息做出迅速反应,我需要在发送方的每个执行步骤中自我发送消息(即,在将A、B发送给Stdout actor之后)。在我看来,做这些事情的正确方式太难了:)

我还尝试使用其他scala语言构造(例如异步发送、响应等)开发其他解决方案,但在某种程度上,它们似乎会影响到其他问题/技巧


是否有人有更好的解决方案来处理scala actors中自治和反应行为的集成?

如果我理解正确,您应该使用Akka actors,特别是Akka FSM,将发送方建模为状态机。Akka参与者有一个内置的停止机制,或者您可以始终使用自己的消息,当未处理时,可以通过
处理程序从所有状态处理这些消息

这显然是过火了,但我想你是想做更复杂的事情。您还可以使用
Stdout
“监视”
Sender
,使其在
Sender
终止时终止,而不是在收到特定消息时终止。看


无论您如何在发送方中实现状态,如果您想使用参与者对其进行建模,我相信您将需要“自发送”消息,无论是在事件处理中,还是在我上面提到的计时器中。

从一个react或receive块中的一个参与者按顺序发送的消息都将按该顺序接收。(你可能会有来自其他演员的其他消息散布,但你不会先发送A,然后发送B,然后发送A。)

所以你可以

stdout ! A
stdout ! B
stdout ! C

除非你还需要做别的事情。

是的,我知道。但是在实际应用程序中,我需要按顺序检索回复(这就是为什么我使用!?)。此外,如问题中所述,我需要将这种主动行为与从StopNotifier接收stop相关联的被动行为结合起来。@the_dark_destructor-!?是同步的——在得到回复之前,你不会从那一点开始传递,所以你无论如何也不能对停止做出如此迅速的响应。如果可以等一个,为什么不能等三个呢?我明白了。。。我肯定会有一个更好的看阿卡FSM的演员然后(我不知道阿卡)。然而,在您的回复之后,我觉得我采用的基于scala的解决方案最适合解决此类问题,对吗?正如你所说,“自我发送”消息成为强制性的,以实现自治行为和反应行为之间的那种集成。@u dark_析构函数这个问题可能太开放了。如果您需要并发性,那么Akka演员可能是最佳选择。不过,这可能有点过头了。请注意,我没有意识到您需要对stdout的调用是同步的。这让我相信这是过分的。您应该使用
而不是
以找回未来。
package fsmTest

import akka.actor._
import akka.util.duration._

sealed trait Msg
case object A extends Msg
case object B extends Msg
case object C extends Msg

sealed trait SenderState
case object Started extends SenderState
case object SentA extends SenderState
case object SentB extends SenderState

case class SenderData()

class Sender(stdout: ActorRef) 
  extends Actor 
  with FSM[SenderState, SenderData] {

  case object GoNextState

  startWith(Started, SenderData())

  when(Started) {
    case Event(GoNextState, data) => {
      stdout ! A
      goto(SentA) using data
    }
  }

  when(SentA) {
    case Event(GoNextState, data) => {
      stdout ! B
      goto(SentB) using data
    }
  }

  when(SentB) {
    case Event(GoNextState, data) => {
      stdout ! C
      goto(Started) using data
    }
  }

//      //Handle messages which aren't explicitly handled in state here
//      whenUnhandled {
//        case Event(SomeCustomStop, data) => {
//          stop(FSM.Shutdown)
//        }
//      }

  setTimer("goNextState", GoNextState, 1 second, repeat = true)

  initialize
}

class Stdout() extends Actor {
  def receive = {
    case msg: Msg => {
      context.watch(sender) //Not sure if you're gonna want to do this here, but you get the point
      println(msg)
    }
    case Terminated(_) => context.stop(self)
  }
}

object FSMTest extends App {

  implicit val system = ActorSystem("Testing")
  val stdout = system.actorOf(Props[Stdout], "stdout")
  val sender = system.actorOf(Props(new Sender(stdout)), "sender")

  system.scheduler.scheduleOnce(5 seconds) {
    system.stop(sender)
    system.shutdown()
  }
  system.awaitTermination(10 seconds)
}
stdout ! A
stdout ! B
stdout ! C