ActorRef provides location-transparent references to actors with immutable message passing, while ActorSelection enables pattern-based actor lookup and communication.
Immutable, serializable handles to actors supporting location-transparent message passing.
/**
* Immutable reference to an actor, local or remote
*/
abstract class ActorRef extends java.lang.Comparable[ActorRef] with Serializable {
/**
* Send message with fire-and-forget semantics (Scala API)
* @param message - Message to send
* @param sender - Implicit sender reference
*/
def !(message: Any)(implicit sender: ActorRef = Actor.noSender): Unit
/**
* Send message with explicit sender (Java API)
* @param msg - Message to send
* @param sender - Sender reference
*/
def tell(msg: Any, sender: ActorRef): Unit
/**
* Forward message preserving original sender
* @param message - Message to forward
* @param context - Implicit actor context
*/
def forward(message: Any)(implicit context: ActorContext): Unit
/**
* Hierarchical path to this actor
*/
def path: ActorPath
/**
* Compare actors by path and unique identifier
* @param other - ActorRef to compare with
* @return Comparison result
*/
final def compareTo(other: ActorRef): Int
}
object ActorRef {
/**
* Sentinel value for no sender
*/
final val noSender: ActorRef = Actor.noSender
}Usage Examples:
import akka.actor._
// Send messages
val actorRef: ActorRef = system.actorOf(Props[MyActor])
// Fire-and-forget
actorRef ! "hello"
// With explicit sender (from within actor)
class SenderActor extends Actor {
def receive = {
case "forward" =>
actorRef.tell("forwarded message", self)
case "relay" =>
actorRef.forward("relayed message")
}
}
// Path access
println(s"Actor path: ${actorRef.path}")
println(s"Actor name: ${actorRef.path.name}")Hierarchical addressing system for actors with support for relative and absolute paths.
/**
* Hierarchical path uniquely identifying an actor
*/
sealed trait ActorPath extends Comparable[ActorPath] {
/**
* Actor system address
*/
def address: Address
/**
* Path elements from root to this actor
*/
def elements: immutable.Iterable[String]
/**
* Actor name (last element of path)
*/
def name: String
/**
* Parent path (all but last element)
*/
def parent: ActorPath
/**
* Root path of the actor system
*/
def root: RootActorPath
/**
* Create child path
* @param child - Child actor name
* @return Child actor path
*/
def /(child: String): ActorPath
/**
* Create descendant path from sequence
* @param children - Sequence of child names
* @return Descendant actor path
*/
def /(children: Iterable[String]): ActorPath
/**
* Unique identifier for this actor instance
*/
def uid: Int
/**
* Convert to string representation
*/
def toStringWithoutAddress: String
/**
* Convert to string with address
*/
override def toString: String
}
/**
* Root path of actor system
*/
class RootActorPath(val address: Address, val name: String = "/") extends ActorPath
/**
* Child path within actor hierarchy
*/
class ChildActorPath(val parent: ActorPath, val name: String, val uid: Int) extends ActorPathUsage Examples:
// Path manipulation
val systemPath = ActorPath.fromString("akka://MySystem@127.0.0.1:2552/")
val userPath = systemPath / "user"
val childPath = userPath / "myActor"
val descendantPath = systemPath / List("user", "parent", "child")
// Path information
println(s"Actor name: ${childPath.name}")
println(s"Parent path: ${childPath.parent}")
println(s"Full path: ${childPath}")
println(s"Without address: ${childPath.toStringWithoutAddress}")
// Path comparison and equality
val path1 = ActorPath.fromString("akka://System/user/actor")
val path2 = ActorPath.fromString("akka://System/user/actor")
println(s"Paths equal: ${path1 == path2}")Pattern-based actor lookup supporting wildcards and path traversal.
/**
* Selection of actors by path pattern with wildcard support
*/
abstract class ActorSelection {
/**
* Send message to all selected actors
* @param msg - Message to send
* @param sender - Implicit sender reference
*/
def !(msg: Any)(implicit sender: ActorRef = Actor.noSender): Unit
/**
* Send message with explicit sender
* @param msg - Message to send
* @param sender - Sender reference
*/
def tell(msg: Any, sender: ActorRef): Unit
/**
* Forward message to selected actors
* @param msg - Message to forward
* @param context - Implicit actor context
*/
def forward(msg: Any)(implicit context: ActorContext): Unit
/**
* Resolve selection to single ActorRef
* @param timeout - Resolution timeout
* @return Future[ActorRef] if single actor found
* @throws ActorNotFound if no actor or multiple actors found
*/
def resolveOne()(implicit timeout: Timeout): Future[ActorRef]
/**
* Path pattern this selection represents
*/
def pathString: String
/**
* Anchor ActorRef for relative selections
*/
def anchor: ActorRef
}Usage Examples:
import akka.util.Timeout
import scala.concurrent.duration._
import akka.pattern.ask
// Actor selection patterns
val system = ActorSystem("SelectionExample")
// Select by absolute path
val userGuardian = system.actorSelection("/user")
val specificActor = system.actorSelection("/user/myActor")
// Wildcard selections
val allUserChildren = system.actorSelection("/user/*")
val allDescendants = system.actorSelection("/user/**")
// Relative selections (from within actor)
class SelectingActor extends Actor {
def receive = {
case "selectSibling" =>
val sibling = context.actorSelection("../siblingActor")
sibling ! "hello"
case "selectChild" =>
val child = context.actorSelection("childActor")
child ! "message"
case "selectDescendant" =>
val descendant = context.actorSelection("*/deeply/nested/actor")
descendant ! "deep message"
}
}
// Resolve selection to ActorRef
implicit val timeout = Timeout(5.seconds)
val selection = system.actorSelection("/user/myActor")
val futureRef: Future[ActorRef] = selection.resolveOne()
futureRef.onComplete {
case Success(actorRef) => println(s"Found actor: $actorRef")
case Failure(exception) => println(s"Actor not found: $exception")
}
// Send to multiple actors via wildcard
system.actorSelection("/user/worker-*") ! "broadcast message"Actor execution environment providing access to system resources and lifecycle management.
/**
* Execution context for actor behavior
*/
trait ActorContext extends ActorRefFactory {
/**
* Create child actor with generated name
* @param props - Props for child actor
* @return ActorRef to child
*/
def actorOf(props: Props): ActorRef
/**
* Create named child actor
* @param props - Props for child actor
* @param name - Unique child name
* @return ActorRef to child
*/
def actorOf(props: Props, name: String): ActorRef
/**
* Select actors by path pattern
* @param path - Selection path pattern
* @return ActorSelection for pattern
*/
def actorSelection(path: String): ActorSelection
/**
* Select actors by ActorPath
* @param path - Structured actor path
* @return ActorSelection for path
*/
def actorSelection(path: ActorPath): ActorSelection
/**
* Stop child actor
* @param actor - Child ActorRef to stop
*/
def stop(actor: ActorRef): Unit
/**
* Watch actor for termination
* @param actor - ActorRef to watch
* @return The watched ActorRef
*/
def watch(actor: ActorRef): ActorRef
/**
* Stop watching actor
* @param actor - ActorRef to unwatch
* @return The unwatched ActorRef
*/
def unwatch(actor: ActorRef): ActorRef
/**
* Current child actors
*/
def children: immutable.Iterable[ActorRef]
/**
* Get child by name
* @param name - Child actor name
* @return Some(ActorRef) if found, None otherwise
*/
def child(name: String): Option[ActorRef]
/**
* Reference to this actor
*/
def self: ActorRef
/**
* Sender of current message
*/
def sender(): ActorRef
/**
* Parent actor reference
*/
def parent: ActorRef
/**
* Actor system reference
*/
def system: ActorSystem
/**
* Current message dispatcher
*/
def dispatcher: ExecutionContext
/**
* Change actor behavior
* @param behavior - New receive function
* @param discardOld - Whether to discard current behavior
*/
def become(behavior: Actor.Receive, discardOld: Boolean = true): Unit
/**
* Revert to previous behavior
*/
def unbecome(): Unit
/**
* Set receive timeout
* @param timeout - Timeout duration
*/
def setReceiveTimeout(timeout: Duration): Unit
/**
* Current receive timeout
*/
def receiveTimeout: Duration
}Usage Examples:
class ContextUsingActor extends Actor {
def receive = {
case "createChild" =>
val child = context.actorOf(Props[ChildActor], "child-1")
sender() ! s"Created child: ${child.path}"
case "listChildren" =>
val childNames = context.children.map(_.path.name).mkString(", ")
sender() ! s"Children: $childNames"
case "watchChild" =>
context.child("child-1") match {
case Some(child) =>
context.watch(child)
sender() ! "Now watching child"
case None =>
sender() ! "Child not found"
}
case "selectSibling" =>
val sibling = context.actorSelection("../sibling")
sibling ! "hello from sibling"
case "changeBehavior" =>
context.become {
case "reset" => context.unbecome()
case msg => sender() ! s"New behavior received: $msg"
}
case "setTimeout" =>
context.setReceiveTimeout(30.seconds)
case ReceiveTimeout =>
println("No messages received within timeout period")
}
}/**
* System address for remote communication
*/
case class Address(
protocol: String,
system: String,
host: Option[String] = None,
port: Option[Int] = None
) {
def hasGlobalScope: Boolean
def hasLocalScope: Boolean
override def toString: String
}
/**
* Message envelope with sender information
*/
case class Envelope(message: Any, sender: ActorRef) {
def copy(message: Any = this.message, sender: ActorRef = this.sender): Envelope
}
/**
* Factory interface for creating actors
*/
trait ActorRefFactory {
def actorOf(props: Props): ActorRef
def actorOf(props: Props, name: String): ActorRef
def stop(actor: ActorRef): Unit
}
/**
* Serializable actor reference
*/
@SerialVersionUID(1L)
private[akka] final case class SerializedActorRef private (path: String) {
def this(actorRef: ActorRef)
def readResolve(): AnyRef
}