关于Akka Actor中receive方法实现的两个技术疑问
Akka Actor Receive方法的两个常见疑问解答
先把你实现的receive方法代码整理下,方便参考:
override def receive: Receive = { case SetRequest(key, value) => { log.info("Received SetRequest - key:{} ,value:{}", key, value) map.put(key, value) sender() ! Status.Success } case GetRequest(key) => { log.info("Received GetRequest for - key:{}", key) val response: Option[Object] = map.get(key) response match { case Some(x) => sender() ! x case None => sender() ! Status.Failure(new KeyNotFoundException(key)) } } case o => Status.Failure(new ClassNotFoundException()) }
疑问1:你的receive实现为何符合Actor.Receive的类型定义?
咱们先把Actor.Receive的本质拆透:它就是scala.PartialFunction[scala.Any, scala.Unit]的类型别名。那什么是PartialFunction?简单说,它是一种只对输入的部分值有定义的函数,而且天生支持模式匹配。
你的receive实现完美贴合这个类型要求:
- 输入类型是
Any:Actor接收的所有消息都是Any类型,你的三个case分支分别匹配SetRequest、GetRequest(这俩都是Any的子类),最后的case o兜底匹配所有剩余的Any对象,覆盖了消息的所有可能类型。 - 输出类型是
Unit:每个case分支里的代码都是执行副作用操作(打印日志、修改map、发送响应),没有返回具体业务值,Scala中没有显式return的代码块默认返回Unit,刚好符合输出类型要求。
说白了,你写的这堆case语句,Scala会自动把它编译成一个PartialFunction[Any, Unit]实例,和Actor.Receive的类型完全对齐,所以能直接赋值给receive方法。
疑问2:这种模式匹配的写法是什么形式?receive看起来没接收参数,实际在匹配什么?
这种写法是Scala偏函数的字面量形式——你不用像写普通函数那样显式声明def func(input: Any): Unit = input match { ... },直接用一系列case语句就能定义偏函数的逻辑。
至于“receive看起来没参数”的问题,其实是因为receive方法不是直接用来接收消息的:它的作用是返回一个PartialFunction,而Akka的Actor运行时会在收到消息时,把消息作为参数传入到你返回的偏函数里执行。
举个直白的例子:当Actor收到一个SetRequest消息时,Akka内部会悄悄做这些事:
val incomingMessage = SetRequest("user1", "Alice") val messageHandler = receive // 获取你定义的偏函数 messageHandler(incomingMessage) // 把消息传给偏函数,触发对应的case分支
所以你写的case语句,本质上是在匹配Actor收到的消息对象,只是这个参数传递的过程被Akka封装起来了,不用你显式写出来而已。
内容的提问来源于stack exchange,提问作者Mandroid
相关产品推荐
相关产品推荐

