Merge paradox/scala/mailboxes.md and java/mailboxes.md (#23191)
This commit is contained in:
parent
2b2923f1b6
commit
71175eaf54
4 changed files with 87 additions and 297 deletions
|
|
@ -1,273 +0,0 @@
|
||||||
# Mailboxes
|
|
||||||
|
|
||||||
An Akka `Mailbox` holds the messages that are destined for an `Actor`.
|
|
||||||
Normally each `Actor` has its own mailbox, but with for example a `BalancingPool`
|
|
||||||
all routees will share a single mailbox instance.
|
|
||||||
|
|
||||||
## Mailbox Selection
|
|
||||||
|
|
||||||
### Requiring a Message Queue Type for an Actor
|
|
||||||
|
|
||||||
It is possible to require a certain type of message queue for a certain type of actor
|
|
||||||
by having that actor implement the parameterized interface `RequiresMessageQueue`. Here is
|
|
||||||
an example:
|
|
||||||
|
|
||||||
@@snip [MyBoundedActor.java]($code$/java/jdocs/actor/MyBoundedActor.java) { #my-bounded-untyped-actor }
|
|
||||||
|
|
||||||
The type parameter to the `RequiresMessageQueue` interface needs to be mapped to a mailbox in
|
|
||||||
configuration like this:
|
|
||||||
|
|
||||||
@@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #bounded-mailbox-config #required-mailbox-config }
|
|
||||||
|
|
||||||
Now every time you create an actor of type `MyBoundedActor` it will try to get a bounded
|
|
||||||
mailbox. If the actor has a different mailbox configured in deployment, either directly or via
|
|
||||||
a dispatcher with a specified mailbox type, then that will override this mapping.
|
|
||||||
|
|
||||||
@@@ note
|
|
||||||
|
|
||||||
The type of the queue in the mailbox created for an actor will be checked against the required type in the
|
|
||||||
interface and if the queue doesn't implement the required type then actor creation will fail.
|
|
||||||
|
|
||||||
@@@
|
|
||||||
|
|
||||||
### Requiring a Message Queue Type for a Dispatcher
|
|
||||||
|
|
||||||
A dispatcher may also have a requirement for the mailbox type used by the
|
|
||||||
actors running on it. An example is the BalancingDispatcher which requires a
|
|
||||||
message queue that is thread-safe for multiple concurrent consumers. Such a
|
|
||||||
requirement is formulated within the dispatcher configuration section like
|
|
||||||
this:
|
|
||||||
|
|
||||||
```
|
|
||||||
my-dispatcher {
|
|
||||||
mailbox-requirement = org.example.MyInterface
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The given requirement names a class or interface which will then be ensured to
|
|
||||||
be a supertype of the message queue’s implementation. In case of a
|
|
||||||
conflict—e.g. if the actor requires a mailbox type which does not satisfy this
|
|
||||||
requirement—then actor creation will fail.
|
|
||||||
|
|
||||||
### How the Mailbox Type is Selected
|
|
||||||
|
|
||||||
When an actor is created, the `ActorRefProvider` first determines the
|
|
||||||
dispatcher which will execute it. Then the mailbox is determined as follows:
|
|
||||||
|
|
||||||
1. If the actor’s deployment configuration section contains a `mailbox` key
|
|
||||||
then that names a configuration section describing the mailbox type to be
|
|
||||||
used.
|
|
||||||
2. If the actor’s `Props` contains a mailbox selection—i.e. `withMailbox`
|
|
||||||
was called on it—then that names a configuration section describing the
|
|
||||||
mailbox type to be used.
|
|
||||||
3. If the dispatcher’s configuration section contains a `mailbox-type` key
|
|
||||||
the same section will be used to configure the mailbox type.
|
|
||||||
4. If the actor requires a mailbox type as described above then the mapping for
|
|
||||||
that requirement will be used to determine the mailbox type to be used; if
|
|
||||||
that fails then the dispatcher’s requirement—if any—will be tried instead.
|
|
||||||
5. If the dispatcher requires a mailbox type as described above then the
|
|
||||||
mapping for that requirement will be used to determine the mailbox type to
|
|
||||||
be used.
|
|
||||||
6. The default mailbox `akka.actor.default-mailbox` will be used.
|
|
||||||
|
|
||||||
### Default Mailbox
|
|
||||||
|
|
||||||
When the mailbox is not specified as described above the default mailbox
|
|
||||||
is used. By default it is an unbounded mailbox, which is backed by a
|
|
||||||
`java.util.concurrent.ConcurrentLinkedQueue`.
|
|
||||||
|
|
||||||
`SingleConsumerOnlyUnboundedMailbox` is an even more efficient mailbox, and
|
|
||||||
it can be used as the default mailbox, but it cannot be used with a BalancingDispatcher.
|
|
||||||
|
|
||||||
Configuration of `SingleConsumerOnlyUnboundedMailbox` as default mailbox:
|
|
||||||
|
|
||||||
```
|
|
||||||
akka.actor.default-mailbox {
|
|
||||||
mailbox-type = "akka.dispatch.SingleConsumerOnlyUnboundedMailbox"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Which Configuration is passed to the Mailbox Type
|
|
||||||
|
|
||||||
Each mailbox type is implemented by a class which extends `MailboxType`
|
|
||||||
and takes two constructor arguments: a `ActorSystem.Settings` object and
|
|
||||||
a `Config` section. The latter is computed by obtaining the named
|
|
||||||
configuration section from the actor system’s configuration, overriding its
|
|
||||||
`id` key with the configuration path of the mailbox type and adding a
|
|
||||||
fall-back to the default mailbox configuration section.
|
|
||||||
|
|
||||||
## Builtin Mailbox Implementations
|
|
||||||
|
|
||||||
Akka comes shipped with a number of mailbox implementations:
|
|
||||||
|
|
||||||
*
|
|
||||||
**UnboundedMailbox** (default)
|
|
||||||
* The default mailbox
|
|
||||||
* Backed by a `java.util.concurrent.ConcurrentLinkedQueue`
|
|
||||||
* Blocking: No
|
|
||||||
* Bounded: No
|
|
||||||
* Configuration name: `"unbounded"` or `"akka.dispatch.UnboundedMailbox"`
|
|
||||||
*
|
|
||||||
**SingleConsumerOnlyUnboundedMailbox**
|
|
||||||
This queue may or may not be faster than the default one depending on your use-case—be sure to benchmark properly!
|
|
||||||
* Backed by a Multiple-Producer Single-Consumer queue, cannot be used with `BalancingDispatcher`
|
|
||||||
* Blocking: No
|
|
||||||
* Bounded: No
|
|
||||||
* Configuration name: `"akka.dispatch.SingleConsumerOnlyUnboundedMailbox"`
|
|
||||||
*
|
|
||||||
**NonBlockingBoundedMailbox**
|
|
||||||
* Backed by a very efficient Multiple-Producer Single-Consumer queue
|
|
||||||
* Blocking: No (discards overflowing messages into deadLetters)
|
|
||||||
* Bounded: Yes
|
|
||||||
* Configuration name: `"akka.dispatch.NonBlockingBoundedMailbox"`
|
|
||||||
*
|
|
||||||
**UnboundedControlAwareMailbox**
|
|
||||||
* Delivers messages that extend `akka.dispatch.ControlMessage` with higher priority
|
|
||||||
* Backed by two `java.util.concurrent.ConcurrentLinkedQueue`
|
|
||||||
* Blocking: No
|
|
||||||
* Bounded: No
|
|
||||||
* Configuration name: "akka.dispatch.UnboundedControlAwareMailbox"
|
|
||||||
*
|
|
||||||
**UnboundedPriorityMailbox**
|
|
||||||
* Backed by a `java.util.concurrent.PriorityBlockingQueue`
|
|
||||||
* Delivery order for messages of equal priority is undefined - contrast with the UnboundedStablePriorityMailbox
|
|
||||||
* Blocking: No
|
|
||||||
* Bounded: No
|
|
||||||
* Configuration name: "akka.dispatch.UnboundedPriorityMailbox"
|
|
||||||
*
|
|
||||||
**UnboundedStablePriorityMailbox**
|
|
||||||
* Backed by a `java.util.concurrent.PriorityBlockingQueue` wrapped in an `akka.util.PriorityQueueStabilizer`
|
|
||||||
* FIFO order is preserved for messages of equal priority - contrast with the UnboundedPriorityMailbox
|
|
||||||
* Blocking: No
|
|
||||||
* Bounded: No
|
|
||||||
* Configuration name: "akka.dispatch.UnboundedStablePriorityMailbox"
|
|
||||||
|
|
||||||
Other bounded mailbox implementations which will block the sender if the capacity is reached and
|
|
||||||
configured with non-zero `mailbox-push-timeout-time`.
|
|
||||||
|
|
||||||
@@@ note
|
|
||||||
|
|
||||||
The following mailboxes should only be used with zero `mailbox-push-timeout-time`.
|
|
||||||
|
|
||||||
@@@
|
|
||||||
|
|
||||||
* **BoundedMailbox**
|
|
||||||
* Backed by a `java.util.concurrent.LinkedBlockingQueue`
|
|
||||||
* Blocking: Yes if used with non-zero `mailbox-push-timeout-time`, otherwise No
|
|
||||||
* Bounded: Yes
|
|
||||||
* Configuration name: "bounded" or "akka.dispatch.BoundedMailbox"
|
|
||||||
* **BoundedPriorityMailbox**
|
|
||||||
* Backed by a `java.util.PriorityQueue` wrapped in an `akka.util.BoundedBlockingQueue`
|
|
||||||
* Delivery order for messages of equal priority is undefined - contrast with the `BoundedStablePriorityMailbox`
|
|
||||||
* Blocking: Yes if used with non-zero `mailbox-push-timeout-time`, otherwise No
|
|
||||||
* Bounded: Yes
|
|
||||||
* Configuration name: `"akka.dispatch.BoundedPriorityMailbox"`
|
|
||||||
* **BoundedStablePriorityMailbox**
|
|
||||||
* Backed by a `java.util.PriorityQueue` wrapped in an `akka.util.PriorityQueueStabilizer` and an `akka.util.BoundedBlockingQueue`
|
|
||||||
* FIFO order is preserved for messages of equal priority - contrast with the BoundedPriorityMailbox
|
|
||||||
* Blocking: Yes if used with non-zero `mailbox-push-timeout-time`, otherwise No
|
|
||||||
* Bounded: Yes
|
|
||||||
* Configuration name: "akka.dispatch.BoundedStablePriorityMailbox"
|
|
||||||
* **BoundedControlAwareMailbox**
|
|
||||||
* Delivers messages that extend `akka.dispatch.ControlMessage` with higher priority
|
|
||||||
* Backed by two `java.util.concurrent.ConcurrentLinkedQueue` and blocking on enqueue if capacity has been reached
|
|
||||||
* Blocking: Yes if used with non-zero `mailbox-push-timeout-time`, otherwise No
|
|
||||||
* Bounded: Yes
|
|
||||||
* Configuration name: "akka.dispatch.BoundedControlAwareMailbox"
|
|
||||||
|
|
||||||
## Mailbox configuration examples
|
|
||||||
|
|
||||||
### PriorityMailbox
|
|
||||||
|
|
||||||
How to create a PriorityMailbox:
|
|
||||||
|
|
||||||
@@snip [DispatcherDocTest.java]($code$/java/jdocs/dispatcher/DispatcherDocTest.java) { #prio-mailbox }
|
|
||||||
|
|
||||||
And then add it to the configuration:
|
|
||||||
|
|
||||||
@@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #prio-dispatcher-config }
|
|
||||||
|
|
||||||
And then an example on how you would use it:
|
|
||||||
|
|
||||||
@@snip [DispatcherDocTest.java]($code$/java/jdocs/dispatcher/DispatcherDocTest.java) { #prio-dispatcher }
|
|
||||||
|
|
||||||
It is also possible to configure a mailbox type directly like this:
|
|
||||||
|
|
||||||
@@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #prio-mailbox-config-java #mailbox-deployment-config }
|
|
||||||
|
|
||||||
And then use it either from deployment like this:
|
|
||||||
|
|
||||||
@@snip [DispatcherDocTest.java]($code$/java/jdocs/dispatcher/DispatcherDocTest.java) { #defining-mailbox-in-config }
|
|
||||||
|
|
||||||
Or code like this:
|
|
||||||
|
|
||||||
@@snip [DispatcherDocTest.java]($code$/java/jdocs/dispatcher/DispatcherDocTest.java) { #defining-mailbox-in-code }
|
|
||||||
|
|
||||||
### ControlAwareMailbox
|
|
||||||
|
|
||||||
A `ControlAwareMailbox` can be very useful if an actor needs to be able to receive control messages
|
|
||||||
immediately no matter how many other messages are already in its mailbox.
|
|
||||||
|
|
||||||
It can be configured like this:
|
|
||||||
|
|
||||||
@@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #control-aware-mailbox-config }
|
|
||||||
|
|
||||||
Control messages need to extend the `ControlMessage` trait:
|
|
||||||
|
|
||||||
@@snip [DispatcherDocTest.java]($code$/java/jdocs/dispatcher/DispatcherDocTest.java) { #control-aware-mailbox-messages }
|
|
||||||
|
|
||||||
And then an example on how you would use it:
|
|
||||||
|
|
||||||
@@snip [DispatcherDocTest.java]($code$/java/jdocs/dispatcher/DispatcherDocTest.java) { #control-aware-dispatcher }
|
|
||||||
|
|
||||||
## Creating your own Mailbox type
|
|
||||||
|
|
||||||
An example is worth a thousand quacks:
|
|
||||||
|
|
||||||
@@snip [MyUnboundedMailbox.java]($code$/java/jdocs/dispatcher/MyUnboundedMailbox.java) { #mailbox-implementation-example }
|
|
||||||
|
|
||||||
@@snip [MyUnboundedMessageQueueSemantics.java]($code$/java/jdocs/dispatcher/MyUnboundedMessageQueueSemantics.java) { #mailbox-implementation-example }
|
|
||||||
|
|
||||||
And then you just specify the FQCN of your MailboxType as the value of the "mailbox-type" in the dispatcher
|
|
||||||
configuration, or the mailbox configuration.
|
|
||||||
|
|
||||||
@@@ note
|
|
||||||
|
|
||||||
Make sure to include a constructor which takes
|
|
||||||
`akka.actor.ActorSystem.Settings` and `com.typesafe.config.Config`
|
|
||||||
arguments, as this constructor is invoked reflectively to construct your
|
|
||||||
mailbox type. The config passed in as second argument is that section from
|
|
||||||
the configuration which describes the dispatcher or mailbox setting using
|
|
||||||
this mailbox type; the mailbox type will be instantiated once for each
|
|
||||||
dispatcher or mailbox setting using it.
|
|
||||||
|
|
||||||
@@@
|
|
||||||
|
|
||||||
You can also use the mailbox as a requirement on the dispatcher like this:
|
|
||||||
|
|
||||||
@@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #custom-mailbox-config-java }
|
|
||||||
|
|
||||||
Or by defining the requirement on your actor class like this:
|
|
||||||
|
|
||||||
@@snip [DispatcherDocTest.java]($code$/java/jdocs/dispatcher/DispatcherDocTest.java) { #require-mailbox-on-actor }
|
|
||||||
|
|
||||||
## Special Semantics of `system.actorOf`
|
|
||||||
|
|
||||||
In order to make `system.actorOf` both synchronous and non-blocking while
|
|
||||||
keeping the return type `ActorRef` (and the semantics that the returned
|
|
||||||
ref is fully functional), special handling takes place for this case. Behind
|
|
||||||
the scenes, a hollow kind of actor reference is constructed, which is sent to
|
|
||||||
the system’s guardian actor who actually creates the actor and its context and
|
|
||||||
puts those inside the reference. Until that has happened, messages sent to the
|
|
||||||
`ActorRef` will be queued locally, and only upon swapping the real
|
|
||||||
filling in will they be transferred into the real mailbox. Thus,
|
|
||||||
|
|
||||||
```scala
|
|
||||||
final Props props = ...
|
|
||||||
// this actor uses MyCustomMailbox, which is assumed to be a singleton
|
|
||||||
system.actorOf(props.withDispatcher("myCustomMailbox").tell("bang", sender);
|
|
||||||
assert(MyCustomMailbox.getInstance().getLastEnqueued().equals("bang"));
|
|
||||||
```
|
|
||||||
|
|
||||||
will probably fail; you will have to allow for some time to pass and retry the
|
|
||||||
check à la `TestKit.awaitCond`.
|
|
||||||
1
akka-docs/src/main/paradox/java/mailboxes.md
Symbolic link
1
akka-docs/src/main/paradox/java/mailboxes.md
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../scala/mailboxes.md
|
||||||
|
|
@ -9,12 +9,16 @@ all routees will share a single mailbox instance.
|
||||||
### Requiring a Message Queue Type for an Actor
|
### Requiring a Message Queue Type for an Actor
|
||||||
|
|
||||||
It is possible to require a certain type of message queue for a certain type of actor
|
It is possible to require a certain type of message queue for a certain type of actor
|
||||||
by having that actor extend the parameterized trait `RequiresMessageQueue`. Here is
|
by having that actor @scala[extend]@java[implement] the parameterized @scala[trait]@java[interface] `RequiresMessageQueue`. Here is
|
||||||
an example:
|
an example:
|
||||||
|
|
||||||
@@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #required-mailbox-class }
|
Scala
|
||||||
|
: @@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #required-mailbox-class }
|
||||||
|
|
||||||
The type parameter to the `RequiresMessageQueue` trait needs to be mapped to a mailbox in
|
Java
|
||||||
|
: @@snip [MyBoundedActor.java]($code$/java/jdocs/actor/MyBoundedActor.java) { #my-bounded-untyped-actor }
|
||||||
|
|
||||||
|
The type parameter to the `RequiresMessageQueue` @scala[trait]@java[interface] needs to be mapped to a mailbox in
|
||||||
configuration like this:
|
configuration like this:
|
||||||
|
|
||||||
@@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #bounded-mailbox-config #required-mailbox-config }
|
@@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #bounded-mailbox-config #required-mailbox-config }
|
||||||
|
|
@ -26,7 +30,7 @@ a dispatcher with a specified mailbox type, then that will override this mapping
|
||||||
@@@ note
|
@@@ note
|
||||||
|
|
||||||
The type of the queue in the mailbox created for an actor will be checked against the required type in the
|
The type of the queue in the mailbox created for an actor will be checked against the required type in the
|
||||||
trait and if the queue doesn't implement the required type then actor creation will fail.
|
@scala[trait]@java[interface] and if the queue doesn't implement the required type then actor creation will fail.
|
||||||
|
|
||||||
@@@
|
@@@
|
||||||
|
|
||||||
|
|
@ -181,7 +185,11 @@ The following mailboxes should only be used with zero `mailbox-push-timeout-time
|
||||||
|
|
||||||
How to create a PriorityMailbox:
|
How to create a PriorityMailbox:
|
||||||
|
|
||||||
@@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #prio-mailbox }
|
Scala
|
||||||
|
: @@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #prio-mailbox }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [DispatcherDocTest.java]($code$/java/jdocs/dispatcher/DispatcherDocTest.java) { #prio-mailbox }
|
||||||
|
|
||||||
And then add it to the configuration:
|
And then add it to the configuration:
|
||||||
|
|
||||||
|
|
@ -189,19 +197,35 @@ And then add it to the configuration:
|
||||||
|
|
||||||
And then an example on how you would use it:
|
And then an example on how you would use it:
|
||||||
|
|
||||||
@@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #prio-dispatcher }
|
Scala
|
||||||
|
: @@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #prio-dispatcher }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [DispatcherDocTest.java]($code$/java/jdocs/dispatcher/DispatcherDocTest.java) { #prio-dispatcher }
|
||||||
|
|
||||||
It is also possible to configure a mailbox type directly like this:
|
It is also possible to configure a mailbox type directly like this:
|
||||||
|
|
||||||
@@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #prio-mailbox-config #mailbox-deployment-config }
|
Scala
|
||||||
|
: @@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #prio-mailbox-config #mailbox-deployment-config }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #prio-mailbox-config-java #mailbox-deployment-config }
|
||||||
|
|
||||||
And then use it either from deployment like this:
|
And then use it either from deployment like this:
|
||||||
|
|
||||||
@@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #defining-mailbox-in-config }
|
Scala
|
||||||
|
: @@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #defining-mailbox-in-config }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [DispatcherDocTest.java]($code$/java/jdocs/dispatcher/DispatcherDocTest.java) { #defining-mailbox-in-config }
|
||||||
|
|
||||||
Or code like this:
|
Or code like this:
|
||||||
|
|
||||||
@@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #defining-mailbox-in-code }
|
Scala
|
||||||
|
: @@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #defining-mailbox-in-code }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [DispatcherDocTest.java]($code$/java/jdocs/dispatcher/DispatcherDocTest.java) { #defining-mailbox-in-code }
|
||||||
|
|
||||||
### ControlAwareMailbox
|
### ControlAwareMailbox
|
||||||
|
|
||||||
|
|
@ -214,17 +238,36 @@ It can be configured like this:
|
||||||
|
|
||||||
Control messages need to extend the `ControlMessage` trait:
|
Control messages need to extend the `ControlMessage` trait:
|
||||||
|
|
||||||
@@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #control-aware-mailbox-messages }
|
Scala
|
||||||
|
: @@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #control-aware-mailbox-messages }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [DispatcherDocTest.java]($code$/java/jdocs/dispatcher/DispatcherDocTest.java) { #control-aware-mailbox-messages }
|
||||||
|
|
||||||
And then an example on how you would use it:
|
And then an example on how you would use it:
|
||||||
|
|
||||||
@@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #control-aware-dispatcher }
|
Scala
|
||||||
|
: @@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #control-aware-dispatcher }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [DispatcherDocTest.java]($code$/java/jdocs/dispatcher/DispatcherDocTest.java) { #control-aware-dispatcher }
|
||||||
|
|
||||||
## Creating your own Mailbox type
|
## Creating your own Mailbox type
|
||||||
|
|
||||||
An example is worth a thousand quacks:
|
An example is worth a thousand quacks:
|
||||||
|
|
||||||
@@snip [MyUnboundedMailbox.scala]($code$/scala/docs/dispatcher/MyUnboundedMailbox.scala) { #mailbox-implementation-example }
|
Scala
|
||||||
|
: @@snip [MyUnboundedMailbox.scala]($code$/scala/docs/dispatcher/MyUnboundedMailbox.scala) { #mailbox-marker-interface }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [MyUnboundedMessageQueueSemantics.java]($code$/java/jdocs/dispatcher/MyUnboundedMessageQueueSemantics.java) { #mailbox-marker-interface }
|
||||||
|
|
||||||
|
|
||||||
|
Scala
|
||||||
|
: @@snip [MyUnboundedMailbox.scala]($code$/scala/docs/dispatcher/MyUnboundedMailbox.scala) { #mailbox-implementation-example }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [MyUnboundedMailbox.java]($code$/java/jdocs/dispatcher/MyUnboundedMailbox.java) { #mailbox-implementation-example }
|
||||||
|
|
||||||
And then you just specify the FQCN of your MailboxType as the value of the "mailbox-type" in the dispatcher
|
And then you just specify the FQCN of your MailboxType as the value of the "mailbox-type" in the dispatcher
|
||||||
configuration, or the mailbox configuration.
|
configuration, or the mailbox configuration.
|
||||||
|
|
@ -247,7 +290,11 @@ You can also use the mailbox as a requirement on the dispatcher like this:
|
||||||
|
|
||||||
Or by defining the requirement on your actor class like this:
|
Or by defining the requirement on your actor class like this:
|
||||||
|
|
||||||
@@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #require-mailbox-on-actor }
|
Scala
|
||||||
|
: @@snip [DispatcherDocSpec.scala]($code$/scala/docs/dispatcher/DispatcherDocSpec.scala) { #require-mailbox-on-actor }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [DispatcherDocTest.java]($code$/java/jdocs/dispatcher/DispatcherDocTest.java) { #require-mailbox-on-actor }
|
||||||
|
|
||||||
## Special Semantics of `system.actorOf`
|
## Special Semantics of `system.actorOf`
|
||||||
|
|
||||||
|
|
@ -260,12 +307,25 @@ puts those inside the reference. Until that has happened, messages sent to the
|
||||||
`ActorRef` will be queued locally, and only upon swapping the real
|
`ActorRef` will be queued locally, and only upon swapping the real
|
||||||
filling in will they be transferred into the real mailbox. Thus,
|
filling in will they be transferred into the real mailbox. Thus,
|
||||||
|
|
||||||
```scala
|
Scala
|
||||||
val props: Props = ...
|
: @@@vars
|
||||||
// this actor uses MyCustomMailbox, which is assumed to be a singleton
|
```scala
|
||||||
system.actorOf(props.withDispatcher("myCustomMailbox")) ! "bang"
|
val props: Props = ...
|
||||||
assert(MyCustomMailbox.instance.getLastEnqueuedMessage == "bang")
|
// this actor uses MyCustomMailbox, which is assumed to be a singleton
|
||||||
```
|
system.actorOf(props.withDispatcher("myCustomMailbox")) ! "bang"
|
||||||
|
assert(MyCustomMailbox.instance.getLastEnqueuedMessage == "bang")
|
||||||
|
```
|
||||||
|
@@@
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@@vars
|
||||||
|
```java
|
||||||
|
final Props props = ...
|
||||||
|
// this actor uses MyCustomMailbox, which is assumed to be a singleton
|
||||||
|
system.actorOf(props.withDispatcher("myCustomMailbox").tell("bang", sender);
|
||||||
|
assert(MyCustomMailbox.getInstance().getLastEnqueued().equals("bang"));
|
||||||
|
```
|
||||||
|
@@@
|
||||||
|
|
||||||
will probably fail; you will have to allow for some time to pass and retry the
|
will probably fail; you will have to allow for some time to pass and retry the
|
||||||
check à la `TestKit.awaitCond`.
|
check à la `TestKit.awaitCond`.
|
||||||
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
package jdocs.dispatcher;
|
package jdocs.dispatcher;
|
||||||
|
|
||||||
//#mailbox-implementation-example
|
//#mailbox-marker-interface
|
||||||
// Marker interface used for mailbox requirements mapping
|
// Marker interface used for mailbox requirements mapping
|
||||||
public interface MyUnboundedMessageQueueSemantics {
|
public interface MyUnboundedMessageQueueSemantics {
|
||||||
}
|
}
|
||||||
//#mailbox-implementation-example
|
//#mailbox-marker-interface
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,6 @@ import com.typesafe.config.Config
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue
|
import java.util.concurrent.ConcurrentLinkedQueue
|
||||||
import scala.Option
|
import scala.Option
|
||||||
|
|
||||||
// Marker trait used for mailbox requirements mapping
|
|
||||||
trait MyUnboundedMessageQueueSemantics
|
|
||||||
|
|
||||||
object MyUnboundedMailbox {
|
object MyUnboundedMailbox {
|
||||||
// This is the MessageQueue implementation
|
// This is the MessageQueue implementation
|
||||||
class MyMessageQueue extends MessageQueue
|
class MyMessageQueue extends MessageQueue
|
||||||
|
|
@ -58,3 +55,8 @@ class MyUnboundedMailbox extends MailboxType
|
||||||
new MyMessageQueue()
|
new MyMessageQueue()
|
||||||
}
|
}
|
||||||
//#mailbox-implementation-example
|
//#mailbox-implementation-example
|
||||||
|
|
||||||
|
//#mailbox-marker-interface
|
||||||
|
// Marker trait used for mailbox requirements mapping
|
||||||
|
trait MyUnboundedMessageQueueSemantics
|
||||||
|
//#mailbox-marker-interface
|
||||||
Loading…
Add table
Add a link
Reference in a new issue