Scala并发编程的react、loop方法详解
在 Scala 中编写并发应用程序,我们通常会使用 Actor
和 ActorSystem
来创建和管理 Actor,而 react
和 loop
方法则是 Actor
的两个重要方法。
1. react
方法:
react
方法是 Actor
类中最基本的消息处理方法。它将阻塞当前线程,直到 Actor 接收到一条消息或超时。一旦接收到消息,react
方法会调用 receive
方法来处理消息,并且只会处理完一条消息后才会再次调用 react
方法阻塞等待下一条消息。
class MyActor extends Actor {def receive: Receive = {case "Hello" => println("Received Hello message")case "World" => println("Received World message")case other => println(s"Received other message $other")}def act(): Unit = {loop {react {case msg =>receive(msg)}}}
}
在上述示例中,我们定义了一个 MyActor
类,重写了 receive
和 act
方法。在 act
方法中,我们使用了 loop
和 react
方法来循环处理消息,一旦接收到消息,就调用 receive
方法进行处理。
2. loop
方法:
loop
方法是 Actor
类中另一个常用的方法,它是在 react
方法基础上抽象出来的更高级的方法,用于实现更加复杂的消息循环逻辑。
class MyActor extends Actor {def receive: Receive = {case "Hello" => println("Received Hello message")case "World" => println("Received World message")case other => println(s"Received other message $other")}def act(): Unit = {loop {react {case "Exit" =>println("Exiting...")exit()case msg =>receive(msg)}}}
}
在上述示例中,我们在 loop
方法中额外处理了一种 “Exit” 消息,并调用了 exit
方法退出 Actor 的执行。
总之,在 Scala 中,使用 react
和 loop
方法可以很方便地实现消息驱动的并发应用程序。通过使用这些方法,我们可以轻松编写高效、可靠、易于维护和扩展的并发代码。
案例
import java.net.{InetAddress, UnknownHostException}import scala.actors.Actor
import scala.actors.Actor._/*** 1、在Actor类的act方法中,可以使用react方法来替代receive方法进行消息的处理,* 使用react方法的好处是可以在一个线程中执行多个Actor的消息处理函数,* 需要注意的是当react方法接受到的消息匹配到它方法体中的一个偏函数时并进行消息的* 处理后会导致该react方法的退出,这时一般常常在react方法中每个偏函数的最后一行加上* act()方法 使得react方法可以重新关联Actor的邮箱。**(2)由于让消息处理器中的每个偏函数末行加上一个act()方法来负责保持循环继续下去是* 一件很麻烦且很不公平的事情,Scala语言提供了loop组合子来简化这个问题,在Actor的* act()方法和react方法之间使用loop组合子可以生成一个无限的循环,如果想给循环加上一个条件,* 可以把loop换成loopWhile,然后在其后面加上条件判断语句。*/
object NameResolver extends Actor {def act() {/*** 用react方法来替代receive方法进行消息的处理,react允许共享线程资料,* react方法匹配一次并执行完成,然后会退出, 通过再次调用act()方法来重新关联Actor的邮箱。*/
// react {
// case Net(name, actor) =>
// sender ! getIp(name)
// act //通过调用继续处理邮箱信息
// case "EXIT" => println("Name resolver exiting")
// case msg =>
// println("Unhandled message: " + msg)
// act
// }loop { //loop可以循环调用react来处理邮箱的信息react {case Net(name, actor) =>sender ! getIp(name)case msg =>println("Unhandled message: " + msg)}}}def getIp(name: String) : Option[InetAddress] = {try {println(InetAddress.getByName(name))Some(InetAddress.getByName(name))} catch {case _ : UnknownHostException => None}}
}case class Net(name: String, actor: Actor)object Actor_More_Effective {def main(args: Array[String]): Unit = {NameResolver.start()NameResolver ! Net("www.baidu.com", self)println {self.receiveWithin(1000) {case x => x }}}
}