Replacing !!! with ?
This commit is contained in:
parent
fd5afde4ff
commit
fa0478bc32
26 changed files with 102 additions and 100 deletions
|
|
@ -18,7 +18,7 @@ in its mailbox.
|
|||
.. sidebar:: **IMPORTANT**
|
||||
|
||||
None of these mailboxes work with blocking message send, e.g. the message
|
||||
send operations that are relying on futures; ``!!``, ``!!!``,
|
||||
send operations that are relying on futures; ``!!``, ``?``,
|
||||
``sendRequestReply`` and ``ask``. If the node has crashed
|
||||
and then restarted, the thread that was blocked waiting for the reply is gone
|
||||
and there is no way we can deliver the message.
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ Here is the master actor:
|
|||
|
||||
A couple of things are worth explaining further.
|
||||
|
||||
First, we are passing in a ``java.util.concurrent.CountDownLatch`` to the ``Master`` actor. This latch is only used for plumbing (in this specific tutorial), to have a simple way of letting the outside world knowing when the master can deliver the result and shut down. In more idiomatic Akka code, as we will see in part two of this tutorial series, we would not use a latch but other abstractions and functions like ``Channel``, ``Future`` and ``!!!`` to achive the same thing in a non-blocking way. But for simplicity let's stick to a ``CountDownLatch`` for now.
|
||||
First, we are passing in a ``java.util.concurrent.CountDownLatch`` to the ``Master`` actor. This latch is only used for plumbing (in this specific tutorial), to have a simple way of letting the outside world knowing when the master can deliver the result and shut down. In more idiomatic Akka code, as we will see in part two of this tutorial series, we would not use a latch but other abstractions and functions like ``Channel``, ``Future`` and ``?`` to achive the same thing in a non-blocking way. But for simplicity let's stick to a ``CountDownLatch`` for now.
|
||||
|
||||
Second, we are adding a couple of life-cycle callback methods; ``preStart`` and ``postStop``. In the ``preStart`` callback we are recording the time when the actor is started and in the ``postStop`` callback we are printing out the result (the approximation of Pi) and the time it took to calculate it. In this call we also invoke ``latch.countDown`` to tell the outside world that we are done.
|
||||
|
||||
|
|
|
|||
|
|
@ -435,7 +435,7 @@ Here is the master actor::
|
|||
|
||||
A couple of things are worth explaining further.
|
||||
|
||||
First, we are passing in a ``java.util.concurrent.CountDownLatch`` to the ``Master`` actor. This latch is only used for plumbing (in this specific tutorial), to have a simple way of letting the outside world knowing when the master can deliver the result and shut down. In more idiomatic Akka code, as we will see in part two of this tutorial series, we would not use a latch but other abstractions and functions like ``Channel``, ``Future`` and ``!!!`` to achieve the same thing in a non-blocking way. But for simplicity let's stick to a ``CountDownLatch`` for now.
|
||||
First, we are passing in a ``java.util.concurrent.CountDownLatch`` to the ``Master`` actor. This latch is only used for plumbing (in this specific tutorial), to have a simple way of letting the outside world knowing when the master can deliver the result and shut down. In more idiomatic Akka code, as we will see in part two of this tutorial series, we would not use a latch but other abstractions and functions like ``Channel``, ``Future`` and ``?`` to achieve the same thing in a non-blocking way. But for simplicity let's stick to a ``CountDownLatch`` for now.
|
||||
|
||||
Second, we are adding a couple of life-cycle callback methods; ``preStart`` and ``postStop``. In the ``preStart`` callback we are recording the time when the actor is started and in the ``postStop`` callback we are printing out the result (the approximation of Pi) and the time it took to calculate it. In this call we also invoke ``latch.countDown()`` to tell the outside world that we are done.
|
||||
|
||||
|
|
|
|||
|
|
@ -335,7 +335,7 @@ Here is the master actor::
|
|||
|
||||
A couple of things are worth explaining further.
|
||||
|
||||
First, we are passing in a ``java.util.concurrent.CountDownLatch`` to the ``Master`` actor. This latch is only used for plumbing (in this specific tutorial), to have a simple way of letting the outside world knowing when the master can deliver the result and shut down. In more idiomatic Akka code, as we will see in part two of this tutorial series, we would not use a latch but other abstractions and functions like ``Channel``, ``Future`` and ``!!!`` to achieve the same thing in a non-blocking way. But for simplicity let's stick to a ``CountDownLatch`` for now.
|
||||
First, we are passing in a ``java.util.concurrent.CountDownLatch`` to the ``Master`` actor. This latch is only used for plumbing (in this specific tutorial), to have a simple way of letting the outside world knowing when the master can deliver the result and shut down. In more idiomatic Akka code, as we will see in part two of this tutorial series, we would not use a latch but other abstractions and functions like ``Channel``, ``Future`` and ``?`` to achieve the same thing in a non-blocking way. But for simplicity let's stick to a ``CountDownLatch`` for now.
|
||||
|
||||
Second, we are adding a couple of life-cycle callback methods; ``preStart`` and ``postStop``. In the ``preStart`` callback we are recording the time when the actor is started and in the ``postStop`` callback we are printing out the result (the approximation of Pi) and the time it took to calculate it. In this call we also invoke ``latch.countDown`` to tell the outside world that we are done.
|
||||
|
||||
|
|
|
|||
|
|
@ -329,7 +329,7 @@ Here is the master actor::
|
|||
|
||||
A couple of things are worth explaining further.
|
||||
|
||||
First, we are passing in a ``java.util.concurrent.CountDownLatch`` to the ``Master`` actor. This latch is only used for plumbing (in this specific tutorial), to have a simple way of letting the outside world knowing when the master can deliver the result and shut down. In more idiomatic Akka code, as we will see in part two of this tutorial series, we would not use a latch but other abstractions and functions like ``Channel``, ``Future`` and ``!!!`` to achieve the same thing in a non-blocking way. But for simplicity let's stick to a ``CountDownLatch`` for now.
|
||||
First, we are passing in a ``java.util.concurrent.CountDownLatch`` to the ``Master`` actor. This latch is only used for plumbing (in this specific tutorial), to have a simple way of letting the outside world knowing when the master can deliver the result and shut down. In more idiomatic Akka code, as we will see in part two of this tutorial series, we would not use a latch but other abstractions and functions like ``Channel``, ``Future`` and ``?`` to achieve the same thing in a non-blocking way. But for simplicity let's stick to a ``CountDownLatch`` for now.
|
||||
|
||||
Second, we are adding a couple of life-cycle callback methods; ``preStart`` and ``postStop``. In the ``preStart`` callback we are recording the time when the actor is started and in the ``postStop`` callback we are printing out the result (the approximation of Pi) and the time it took to calculate it. In this call we also invoke ``latch.countDown`` to tell the outside world that we are done.
|
||||
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ Messages are sent to an Actor through one of the “bang” methods.
|
|||
|
||||
* ! means “fire-and-forget”, e.g. send a message asynchronously and return immediately.
|
||||
* !! means “send-and-reply-eventually”, e.g. send a message asynchronously and wait for a reply through aFuture. Here you can specify a timeout. Using timeouts is very important. If no timeout is specified then the actor’s default timeout (set by the this.timeout variable in the actor) is used. This method returns an ``Option[Any]`` which will be either ``Some(result)`` if returning successfully or None if the call timed out.
|
||||
* !!! sends a message asynchronously and returns a ``Future``.
|
||||
* ? sends a message asynchronously and returns a ``Future``.
|
||||
|
||||
You can check if an Actor can handle a specific message by invoking the ``isDefinedAt`` method:
|
||||
|
||||
|
|
@ -180,11 +180,11 @@ Here are some examples:
|
|||
Send-And-Receive-Future
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Using ``!!!`` will send a message to the receiving Actor asynchronously and will return a 'Future':
|
||||
Using ``?`` will send a message to the receiving Actor asynchronously and will return a 'Future':
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
val future = actor !!! "Hello"
|
||||
val future = actor ? "Hello"
|
||||
|
||||
See :ref:`futures-scala` for more information.
|
||||
|
||||
|
|
@ -329,7 +329,7 @@ The same pattern holds for using the ``senderFuture`` in the section below.
|
|||
Reply using the sender future
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If a message was sent with the ``!!`` or ``!!!`` methods, which both implements request-reply semantics using Future's, then you either have the option of replying using the ``reply`` method as above. This method will then resolve the Future. But you can also get a reference to the Future directly and resolve it yourself or if you would like to store it away to resolve it later, or pass it on to some other Actor to resolve it.
|
||||
If a message was sent with the ``!!`` or ``?`` methods, which both implements request-reply semantics using Future's, then you either have the option of replying using the ``reply`` method as above. This method will then resolve the Future. But you can also get a reference to the Future directly and resolve it yourself or if you would like to store it away to resolve it later, or pass it on to some other Actor to resolve it.
|
||||
|
||||
The reference to the Future resides in the ``senderFuture: Option[Promise[_]]`` member field in the ``ActorRef`` class.
|
||||
|
||||
|
|
@ -427,7 +427,7 @@ PoisonPill
|
|||
|
||||
You can also send an actor the ``akka.actor.PoisonPill`` message, which will stop the actor when the message is processed.
|
||||
|
||||
If the sender is a ``Future`` (e.g. the message is sent with ``!!`` or ``!!!``), the ``Future`` will be completed with an ``akka.actor.ActorKilledException("PoisonPill")``.
|
||||
If the sender is a ``Future`` (e.g. the message is sent with ``!!`` or ``?``), the ``Future`` will be completed with an ``akka.actor.ActorKilledException("PoisonPill")``.
|
||||
|
||||
HotSwap
|
||||
-------
|
||||
|
|
@ -457,7 +457,7 @@ To hotswap the Actor using ``become``:
|
|||
.. code-block:: scala
|
||||
|
||||
def angry: Receive = {
|
||||
case "foo" => self reply "I am already angry!!!"
|
||||
case "foo" => self reply "I am already angry?"
|
||||
case "bar" => become(happy)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@ Use with Actors
|
|||
|
||||
There are generally two ways of getting a reply from an ``Actor``: the first is by a sent message (``actor ! msg``), which only works if the original sender was an ``Actor``) and the second is through a ``Future``.
|
||||
|
||||
Using an ``Actor``\'s ``!!!`` method to send a message will return a Future. To wait for and retrieve the actual result the simplest method is:
|
||||
Using an ``Actor``\'s ``?`` method to send a message will return a Future. To wait for and retrieve the actual result the simplest method is:
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
val future = actor !!! msg
|
||||
val future = actor ? msg
|
||||
val result: Any = future.get()
|
||||
|
||||
This will cause the current thread to block and wait for the ``Actor`` to 'complete' the ``Future`` with it's reply. Due to the dynamic nature of Akka's ``Actor``\s this result will be untyped and will default to ``Nothing``. The safest way to deal with this is to cast the result to an ``Any`` as is shown in the above example. You can also use the expected result type instead of ``Any``, but if an unexpected type were to be returned you will get a ``ClassCastException``. For more elegant ways to deal with this and to use the result without blocking, refer to `Functional Futures`_.
|
||||
|
|
@ -141,13 +141,13 @@ The example for comprehension above is an example of composing ``Future``\s. A c
|
|||
|
||||
.. code-block:: scala
|
||||
|
||||
val f1 = actor1 !!! msg1
|
||||
val f2 = actor2 !!! msg2
|
||||
val f1 = actor1 ? msg1
|
||||
val f2 = actor2 ? msg2
|
||||
|
||||
val a: Int = f1.get()
|
||||
val b: Int = f2.get()
|
||||
|
||||
val f3 = actor3 !!! (a + b)
|
||||
val f3 = actor3 ? (a + b)
|
||||
|
||||
val result: String = f3.get()
|
||||
|
||||
|
|
@ -155,13 +155,13 @@ Here we wait for the results from the first 2 ``Actor``\s before sending that re
|
|||
|
||||
.. code-block:: scala
|
||||
|
||||
val f1 = actor1 !!! msg1
|
||||
val f2 = actor2 !!! msg2
|
||||
val f1 = actor1 ? msg1
|
||||
val f2 = actor2 ? msg2
|
||||
|
||||
val f3 = for {
|
||||
a: Int <- f1
|
||||
b: Int <- f2
|
||||
c: String <- actor3 !!! (a + b)
|
||||
c: String <- actor3 ? (a + b)
|
||||
} yield c
|
||||
|
||||
val result = f3.get()
|
||||
|
|
@ -173,7 +173,7 @@ This is fine when dealing with a known amount of Actors, but can grow unwieldy i
|
|||
.. code-block:: scala
|
||||
|
||||
// oddActor returns odd numbers sequentially from 1
|
||||
val listOfFutures: List[Future[Int]] = List.fill(100)(oddActor !!! GetNext)
|
||||
val listOfFutures: List[Future[Int]] = List.fill(100)(oddActor ? GetNext)
|
||||
|
||||
// now we have a Future[List[Int]]
|
||||
val futureList = Future.sequence(listOfFutures)
|
||||
|
|
@ -242,7 +242,7 @@ It is also possible to handle an ``Exception`` by returning a different result.
|
|||
|
||||
.. code-block:: scala
|
||||
|
||||
val future = actor !!! msg1 recover {
|
||||
val future = actor ? msg1 recover {
|
||||
case e: ArithmeticException => 0
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue