Merge with master
This commit is contained in:
commit
009853f2f6
168 changed files with 2942 additions and 6005 deletions
|
|
@ -2,4 +2,4 @@ package akka.docs.actor
|
|||
|
||||
import org.scalatest.junit.JUnitSuite
|
||||
|
||||
class UntypedActorTest extends UntypedActorTestBase with JUnitSuite
|
||||
class SchedulerDocTest extends SchedulerDocTestBase with JUnitSuite
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
package akka.docs.actor;
|
||||
|
||||
//#imports1
|
||||
import akka.actor.Props;
|
||||
import akka.util.Duration;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
//#imports1
|
||||
|
||||
//#imports2
|
||||
import akka.actor.UntypedActor;
|
||||
import akka.actor.UntypedActorFactory;
|
||||
import akka.actor.Cancellable;
|
||||
|
||||
//#imports2
|
||||
|
||||
import akka.actor.ActorRef;
|
||||
import akka.actor.ActorSystem;
|
||||
import akka.testkit.AkkaSpec;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class SchedulerDocTestBase {
|
||||
|
||||
ActorSystem system;
|
||||
ActorRef testActor;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
system = ActorSystem.create("MySystem", AkkaSpec.testConf());
|
||||
testActor = system.actorOf(new Props().withCreator(MyUntypedActor.class));
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
system.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scheduleOneOffTask() {
|
||||
//#schedule-one-off-message
|
||||
//Schedules to send the "foo"-message to the testActor after 50ms
|
||||
system.scheduler().scheduleOnce(Duration.create(50, TimeUnit.MILLISECONDS), testActor, "foo");
|
||||
//#schedule-one-off-message
|
||||
|
||||
//#schedule-one-off-thunk
|
||||
//Schedules a Runnable to be executed (send the current time) to the testActor after 50ms
|
||||
system.scheduler().scheduleOnce(Duration.create(50, TimeUnit.MILLISECONDS), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
testActor.tell(System.currentTimeMillis());
|
||||
}
|
||||
});
|
||||
//#schedule-one-off-thunk
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scheduleRecurringTask() {
|
||||
//#schedule-recurring
|
||||
ActorRef tickActor = system.actorOf(new Props().withCreator(new UntypedActorFactory() {
|
||||
public UntypedActor create() {
|
||||
return new UntypedActor() {
|
||||
public void onReceive(Object message) {
|
||||
if (message.equals("Tick")) {
|
||||
// Do someting
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}));
|
||||
|
||||
//This will schedule to send the Tick-message
|
||||
//to the tickActor after 0ms repeating every 50ms
|
||||
Cancellable cancellable = system.scheduler().schedule(Duration.Zero(), Duration.create(50, TimeUnit.MILLISECONDS),
|
||||
tickActor, "Tick");
|
||||
|
||||
//This cancels further Ticks to be sent
|
||||
cancellable.cancel();
|
||||
//#schedule-recurring
|
||||
system.stop(tickActor);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package akka.docs.actor
|
||||
|
||||
import org.scalatest.junit.JUnitSuite
|
||||
|
||||
class UntypedActorDocTest extends UntypedActorDocTestBase with JUnitSuite
|
||||
|
|
@ -4,24 +4,21 @@ package akka.docs.actor;
|
|||
import akka.actor.ActorRef;
|
||||
import akka.actor.ActorSystem;
|
||||
import akka.actor.Props;
|
||||
|
||||
//#imports
|
||||
|
||||
//#import-future
|
||||
import akka.dispatch.Future;
|
||||
import akka.dispatch.Await;
|
||||
import akka.util.Duration;
|
||||
|
||||
import akka.util.Timeout;
|
||||
//#import-future
|
||||
|
||||
//#import-actors
|
||||
import static akka.actor.Actors.*;
|
||||
|
||||
//#import-actors
|
||||
|
||||
//#import-procedure
|
||||
import akka.japi.Procedure;
|
||||
|
||||
//#import-procedure
|
||||
|
||||
import akka.actor.Props;
|
||||
|
|
@ -36,7 +33,26 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class UntypedActorTestBase {
|
||||
public class UntypedActorDocTestBase {
|
||||
|
||||
@Test
|
||||
public void createProps() {
|
||||
//#creating-props-config
|
||||
Props props1 = new Props();
|
||||
Props props2 = new Props(MyUntypedActor.class);
|
||||
Props props3 = new Props(new UntypedActorFactory() {
|
||||
public UntypedActor create() {
|
||||
return new MyUntypedActor();
|
||||
}
|
||||
});
|
||||
Props props4 = props1.withCreator(new UntypedActorFactory() {
|
||||
public UntypedActor create() {
|
||||
return new MyUntypedActor();
|
||||
}
|
||||
});
|
||||
Props props5 = props4.withTimeout(new Timeout(1000));
|
||||
//#creating-props-config
|
||||
}
|
||||
|
||||
@Test
|
||||
public void systemActorOf() {
|
||||
|
|
@ -79,8 +95,8 @@ public class UntypedActorTestBase {
|
|||
//#creating-props
|
||||
MessageDispatcher dispatcher = system.dispatcherFactory().lookup("my-dispatcher");
|
||||
ActorRef myActor = system.actorOf(
|
||||
new Props().withCreator(MyUntypedActor.class).withDispatcher(dispatcher),
|
||||
"myactor");
|
||||
new Props().withCreator(MyUntypedActor.class).withDispatcher(dispatcher),
|
||||
"myactor");
|
||||
//#creating-props
|
||||
myActor.tell("test");
|
||||
system.shutdown();
|
||||
|
|
@ -166,6 +182,8 @@ public class UntypedActorTestBase {
|
|||
}
|
||||
|
||||
public void preRestart(Throwable reason, Option<Object> message) {
|
||||
for (ActorRef each : getContext().getChildren())
|
||||
getContext().stop(each);
|
||||
postStop();
|
||||
}
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ import com.typesafe.config.ConfigFactory;
|
|||
|
||||
import akka.actor.ActorSystem;
|
||||
import akka.docs.actor.MyUntypedActor;
|
||||
import akka.docs.actor.UntypedActorTestBase.MyActor;
|
||||
import akka.docs.actor.UntypedActorDocTestBase.MyActor;
|
||||
import akka.testkit.AkkaSpec;
|
||||
|
||||
public class DispatcherDocTestBase {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
package akka.docs.extension
|
||||
|
||||
import org.scalatest.junit.JUnitSuite
|
||||
|
||||
class ExtensionDocTest extends ExtensionDocTestBase with JUnitSuite
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
package akka.docs.extension;
|
||||
|
||||
//#imports
|
||||
import akka.actor.*;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
//#imports
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class ExtensionDocTestBase {
|
||||
|
||||
//#extension
|
||||
public static class CountExtensionImpl implements Extension {
|
||||
//Since this Extension is a shared instance
|
||||
// per ActorSystem we need to be threadsafe
|
||||
private final AtomicLong counter = new AtomicLong(0);
|
||||
|
||||
//This is the operation this Extension provides
|
||||
public long increment() {
|
||||
return counter.incrementAndGet();
|
||||
}
|
||||
}
|
||||
//#extension
|
||||
|
||||
//#extensionid
|
||||
static class CountExtensionId extends AbstractExtensionId<CountExtensionImpl> {
|
||||
//This method will be called by Akka
|
||||
// to instantiate our Extension
|
||||
public CountExtensionImpl createExtension(ActorSystemImpl i) {
|
||||
return new CountExtensionImpl();
|
||||
}
|
||||
}
|
||||
|
||||
//This will be the identifier of our CountExtension
|
||||
public final static CountExtensionId CountExtension = new CountExtensionId();
|
||||
//#extensionid
|
||||
|
||||
//#extensionid-provider
|
||||
static class CountExtensionIdProvider implements ExtensionIdProvider {
|
||||
public CountExtensionId lookup() {
|
||||
return CountExtension; //The public static final
|
||||
}
|
||||
}
|
||||
//#extensionid-provider
|
||||
|
||||
//#extension-usage-actor
|
||||
static class MyActor extends UntypedActor {
|
||||
public void onReceive(Object msg) {
|
||||
CountExtension.get(getContext().system()).increment();
|
||||
}
|
||||
}
|
||||
//#extension-usage-actor
|
||||
|
||||
|
||||
@Test public void demonstrateHowToCreateAndUseAnAkkaExtensionInJava() {
|
||||
final ActorSystem system = null;
|
||||
try {
|
||||
//#extension-usage
|
||||
CountExtension.get(system).increment();
|
||||
//#extension-usage
|
||||
} catch(Exception e) {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ Dispatchers (Java)
|
|||
.. sidebar:: Contents
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
|
||||
The Dispatcher is an important piece that allows you to configure the right semantics and parameters for optimal performance, throughput and scalability. Different Actors have different needs.
|
||||
|
||||
Akka supports dispatchers for both event-driven lightweight threads, allowing creation of millions of threads on a single workstation, and thread-based Actors, where each dispatcher is bound to a dedicated OS thread.
|
||||
|
|
@ -44,7 +44,7 @@ There are 4 different types of message dispatchers:
|
|||
|
||||
It is recommended to define the dispatcher in :ref:`configuration` to allow for tuning for different environments.
|
||||
|
||||
Example of a custom event-based dispatcher, which can be fetched with ``system.dispatcherFactory().lookup("my-dispatcher")``
|
||||
Example of a custom event-based dispatcher, which can be fetched with ``system.dispatcherFactory().lookup("my-dispatcher")``
|
||||
as in the example above:
|
||||
|
||||
.. includecode:: ../scala/code/akka/docs/dispatcher/DispatcherDocSpec.scala#my-dispatcher-config
|
||||
|
|
@ -115,7 +115,7 @@ Priority event-based
|
|||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Sometimes it's useful to be able to specify priority order of messages, that is done by using Dispatcher and supply
|
||||
an UnboundedPriorityMailbox or BoundedPriorityMailbox with a ``java.util.Comparator[Envelope]`` or use a
|
||||
an UnboundedPriorityMailbox or BoundedPriorityMailbox with a ``java.util.Comparator[Envelope]`` or use a
|
||||
``akka.dispatch.PriorityGenerator`` (recommended).
|
||||
|
||||
Creating a Dispatcher using PriorityGenerator:
|
||||
|
|
@ -129,9 +129,9 @@ Work-sharing event-based
|
|||
|
||||
The ``BalancingDispatcher`` is a variation of the ``Dispatcher`` in which Actors of the same type can be set up to
|
||||
share this dispatcher and during execution time the different actors will steal messages from other actors if they
|
||||
have less messages to process.
|
||||
have less messages to process.
|
||||
Although the technique used in this implementation is commonly known as "work stealing", the actual implementation is probably
|
||||
best described as "work donating" because the actor of which work is being stolen takes the initiative.
|
||||
best described as "work donating" because the actor of which work is being stolen takes the initiative.
|
||||
This can be a great way to improve throughput at the cost of a little higher latency.
|
||||
|
||||
.. includecode:: ../scala/code/akka/docs/dispatcher/DispatcherDocSpec.scala#my-balancing-config
|
||||
|
|
@ -154,8 +154,9 @@ if not specified otherwise.
|
|||
akka {
|
||||
actor {
|
||||
default-dispatcher {
|
||||
task-queue-size = 1000 # If negative (or zero) then an unbounded mailbox is used (default)
|
||||
# If positive then a bounded mailbox is used and the capacity is set to the number specified
|
||||
# If negative (or zero) then an unbounded mailbox is used (default)
|
||||
# If positive then a bounded mailbox is used and the capacity is set to the number specified
|
||||
task-queue-size = 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
63
akka-docs/java/extending-akka.rst
Normal file
63
akka-docs/java/extending-akka.rst
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
.. _extending-akka:
|
||||
|
||||
Akka Extensions
|
||||
===============
|
||||
|
||||
.. sidebar:: Contents
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
If you want to add features to Akka, there is a very elegant, but powerful mechanism for doing so.
|
||||
It's called Akka Extensions and is comprised of 2 basic components: an ``Extension`` and an ``ExtensionId``.
|
||||
|
||||
Extensions will only be loaded once per ``ActorSystem``, which will be managed by Akka.
|
||||
You can choose to have your Extension loaded on-demand or at ``ActorSystem`` creation time through the Akka configuration.
|
||||
Details on how to make that happens are below, in the "Loading from Configuration" section.
|
||||
|
||||
.. warning::
|
||||
|
||||
Since an extension is a way to hook into Akka itself, the implementor of the extension needs to
|
||||
ensure the thread safety of his/her extension.
|
||||
|
||||
|
||||
Building an Extension
|
||||
---------------------
|
||||
|
||||
So let's create a sample extension that just lets us count the number of times something has happened.
|
||||
|
||||
First, we define what our ``Extension`` should do:
|
||||
|
||||
.. includecode:: code/akka/docs/extension/ExtensionDocTestBase.java
|
||||
:include: imports,extension
|
||||
|
||||
Then we need to create an ``ExtensionId`` for our extension so we can grab ahold of it.
|
||||
|
||||
.. includecode:: code/akka/docs/extension/ExtensionDocTestBase.java
|
||||
:include: imports,extensionid
|
||||
|
||||
Wicked! Now all we need to do is to actually use it:
|
||||
|
||||
.. includecode:: code/akka/docs/extension/ExtensionDocTestBase.java
|
||||
:include: extension-usage
|
||||
|
||||
Or from inside of an Akka Actor:
|
||||
|
||||
.. includecode:: code/akka/docs/extension/ExtensionDocTestBase.java
|
||||
:include: extension-usage-actor
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
Loading from Configuration
|
||||
--------------------------
|
||||
|
||||
To be able to load extensions from your Akka configuration you must add FQCNs of implementations of either ``ExtensionId`` or ``ExtensionIdProvider``
|
||||
in the "akka.extensions" section of the config you provide to your ``ActorSystem``.
|
||||
|
||||
.. includecode:: code/akka/docs/extension/ExtensionDocTestBase.java
|
||||
:include: extensionid-provider
|
||||
|
||||
Applicability
|
||||
-------------
|
||||
|
||||
The sky is the limit!
|
||||
By the way, did you know that Akka's ``Typed Actors``, ``Serialization`` and other features are implemented as Akka Extensions?
|
||||
|
|
@ -9,11 +9,12 @@ Java API
|
|||
untyped-actors
|
||||
typed-actors
|
||||
logging
|
||||
scheduler
|
||||
futures
|
||||
dataflow
|
||||
stm
|
||||
transactors
|
||||
fault-tolerance
|
||||
dispatchers
|
||||
routing
|
||||
guice-integration
|
||||
extending-akka
|
||||
|
|
|
|||
|
|
@ -25,14 +25,14 @@ The source object is translated to a String according to the following rules:
|
|||
* in case of a class an approximation of its simpleName
|
||||
* and in all other cases the simpleName of its class
|
||||
|
||||
The log message may contain argument placeholders ``{}``, which will be substituted if the log level
|
||||
The log message may contain argument placeholders ``{}``, which will be substituted if the log level
|
||||
is enabled.
|
||||
|
||||
Event Handler
|
||||
=============
|
||||
|
||||
Logging is performed asynchronously through an event bus. You can configure which event handlers that should
|
||||
subscribe to the logging events. That is done using the 'event-handlers' element in the :ref:`configuration`.
|
||||
Logging is performed asynchronously through an event bus. You can configure which event handlers that should
|
||||
subscribe to the logging events. That is done using the 'event-handlers' element in the :ref:`configuration`.
|
||||
Here you can also define the log level.
|
||||
|
||||
.. code-block:: ruby
|
||||
|
|
@ -40,16 +40,17 @@ Here you can also define the log level.
|
|||
akka {
|
||||
# Event handlers to register at boot time (Logging$DefaultLogger logs to STDOUT)
|
||||
event-handlers = ["akka.event.Logging$DefaultLogger"]
|
||||
loglevel = "DEBUG" # Options: ERROR, WARNING, INFO, DEBUG
|
||||
# Options: ERROR, WARNING, INFO, DEBUG
|
||||
loglevel = "DEBUG"
|
||||
}
|
||||
|
||||
The default one logs to STDOUT and is registered by default. It is not intended to be used for production. There is also an :ref:`slf4j-java`
|
||||
The default one logs to STDOUT and is registered by default. It is not intended to be used for production. There is also an :ref:`slf4j-java`
|
||||
event handler available in the 'akka-slf4j' module.
|
||||
|
||||
Example of creating a listener:
|
||||
|
||||
.. includecode:: code/akka/docs/event/LoggingDocTestBase.java
|
||||
:include: imports,imports-listener,my-event-listener
|
||||
:include: imports,imports-listener,my-event-listener
|
||||
|
||||
|
||||
.. _slf4j-java:
|
||||
|
|
@ -57,7 +58,7 @@ Example of creating a listener:
|
|||
SLF4J
|
||||
=====
|
||||
|
||||
Akka provides an event handler for `SL4FJ <http://www.slf4j.org/>`_. This module is available in the 'akka-slf4j.jar'.
|
||||
Akka provides an event handler for `SL4FJ <http://www.slf4j.org/>`_. This module is available in the 'akka-slf4j.jar'.
|
||||
It has one single dependency; the slf4j-api jar. In runtime you also need a SLF4J backend, we recommend `Logback <http://logback.qos.ch/>`_:
|
||||
|
||||
.. code-block:: xml
|
||||
|
|
@ -69,10 +70,10 @@ It has one single dependency; the slf4j-api jar. In runtime you also need a SLF4
|
|||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
You need to enable the Slf4jEventHandler in the 'event-handlers' element in
|
||||
the :ref:`configuration`. Here you can also define the log level of the event bus.
|
||||
You need to enable the Slf4jEventHandler in the 'event-handlers' element in
|
||||
the :ref:`configuration`. Here you can also define the log level of the event bus.
|
||||
More fine grained log levels can be defined in the configuration of the SLF4J backend
|
||||
(e.g. logback.xml). The String representation of the source object that is used when
|
||||
(e.g. logback.xml). The String representation of the source object that is used when
|
||||
creating the ``LoggingAdapter`` correspond to the name of the SL4FJ logger.
|
||||
|
||||
.. code-block:: ruby
|
||||
|
|
@ -89,9 +90,9 @@ Since the logging is done asynchronously the thread in which the logging was per
|
|||
Mapped Diagnostic Context (MDC) with attribute name ``sourceThread``.
|
||||
With Logback the thread name is available with ``%X{sourceThread}`` specifier within the pattern layout configuration::
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<layout>
|
||||
<pattern>%date{ISO8601} %-5level %logger{36} %X{sourceThread} - %msg%n</pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<layout>
|
||||
<pattern>%date{ISO8601} %-5level %logger{36} %X{sourceThread} - %msg%n</pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
|
|
|
|||
53
akka-docs/java/scheduler.rst
Normal file
53
akka-docs/java/scheduler.rst
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
|
||||
.. _scheduler-java:
|
||||
|
||||
##################
|
||||
Scheduler (Java)
|
||||
##################
|
||||
|
||||
Sometimes the need for making things happen in the future arises, and where do you go look then?
|
||||
Look no further than ``ActorSystem``! There you find the :meth:`scheduler` method that returns an instance
|
||||
of akka.actor.Scheduler, this instance is unique per ActorSystem and is used internally for scheduling things
|
||||
to happen at specific points in time. Please note that the scheduled tasks are executed by the default
|
||||
``MessageDispatcher`` of the ``ActorSystem``.
|
||||
|
||||
You can schedule sending of messages to actors and execution of tasks (functions or Runnable).
|
||||
You will get a ``Cancellable`` back that you can call :meth:`cancel` on to cancel the execution of the
|
||||
scheduled operation.
|
||||
|
||||
Some examples
|
||||
-------------
|
||||
|
||||
.. includecode:: code/akka/docs/actor/SchedulerDocTestBase.java
|
||||
:include: imports1,schedule-one-off-message
|
||||
|
||||
.. includecode:: code/akka/docs/actor/SchedulerDocTestBase.java
|
||||
:include: schedule-one-off-thunk
|
||||
|
||||
.. includecode:: code/akka/docs/actor/SchedulerDocTestBase.java
|
||||
:include: imports1,imports2,schedule-recurring
|
||||
|
||||
From ``akka.actor.ActorSystem``
|
||||
-------------------------------
|
||||
|
||||
.. includecode:: ../../akka-actor/src/main/scala/akka/actor/ActorSystem.scala
|
||||
:include: scheduler
|
||||
|
||||
|
||||
The Scheduler interface
|
||||
-----------------------
|
||||
|
||||
.. includecode:: ../../akka-actor/src/main/scala/akka/actor/Scheduler.scala
|
||||
:include: scheduler
|
||||
|
||||
The Cancellable interface
|
||||
-------------------------
|
||||
|
||||
This allows you to ``cancel`` something that has been scheduled for execution.
|
||||
|
||||
.. warning::
|
||||
This does not abort the execution of the task, if it had already been started.
|
||||
|
||||
.. includecode:: ../../akka-actor/src/main/scala/akka/actor/Scheduler.scala
|
||||
:include: cancellable
|
||||
|
||||
6
akka-docs/java/transactors.rst
Normal file
6
akka-docs/java/transactors.rst
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
.. _transactors-java:
|
||||
|
||||
Transactors (Java)
|
||||
==================
|
||||
|
||||
The Akka Transactors module has not been migrated to Akka 2.0-SNAPSHOT yet.
|
||||
|
|
@ -39,10 +39,27 @@ Here is an example:
|
|||
|
||||
.. includecode:: code/akka/docs/actor/MyUntypedActor.java#my-untyped-actor
|
||||
|
||||
Props
|
||||
-----
|
||||
|
||||
``Props`` is a configuration class to specify options for the creation
|
||||
of actors. Here are some examples on how to create a ``Props`` instance.
|
||||
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java#creating-props-config
|
||||
|
||||
|
||||
Creating Actors with Props
|
||||
--------------------------
|
||||
|
||||
Actors are created by passing in a ``Props`` instance into the ``actorOf`` factory method.
|
||||
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java#creating-props
|
||||
|
||||
|
||||
Creating Actors with default constructor
|
||||
----------------------------------------
|
||||
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java
|
||||
:include: imports,system-actorOf
|
||||
|
||||
The call to :meth:`actorOf` returns an instance of ``ActorRef``. This is a handle to
|
||||
|
|
@ -62,7 +79,7 @@ a top level actor, that is supervised by the system (internal guardian actor).
|
|||
.. includecode:: code/akka/docs/actor/FirstUntypedActor.java#context-actorOf
|
||||
|
||||
Actors are automatically started asynchronously when created.
|
||||
When you create the ``UntypedActor`` then it will automatically call the ``preStart``
|
||||
When you create the ``UntypedActor`` then it will automatically call the ``preStart``
|
||||
callback method on the ``UntypedActor`` class. This is an excellent place to
|
||||
add initialization code for the actor.
|
||||
|
||||
|
|
@ -76,26 +93,16 @@ add initialization code for the actor.
|
|||
Creating Actors with non-default constructor
|
||||
--------------------------------------------
|
||||
|
||||
If your UntypedActor has a constructor that takes parameters then you can't create it using 'actorOf(clazz)'.
|
||||
Instead you can use a variant of ``actorOf`` that takes an instance of an 'UntypedActorFactory'
|
||||
in which you can create the Actor in any way you like. If you use this method then you to make sure that
|
||||
no one can get a reference to the actor instance. If they can get a reference it then they can
|
||||
touch state directly in bypass the whole actor dispatching mechanism and create race conditions
|
||||
which can lead to corrupt data.
|
||||
If your UntypedActor has a constructor that takes parameters then you can't create it using
|
||||
'actorOf(new Props(clazz))'. Then you can instead pass in 'new Props(new UntypedActorFactory() {..})'
|
||||
in which you can create the Actor in any way you like.
|
||||
|
||||
Here is an example:
|
||||
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java#creating-constructor
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java#creating-constructor
|
||||
|
||||
This way of creating the Actor is also great for integrating with Dependency Injection (DI) frameworks like Guice or Spring.
|
||||
|
||||
Creating Actors with Props
|
||||
--------------------------
|
||||
|
||||
``Props`` is a configuration object to specify additional things for the actor to
|
||||
be created, such as the ``MessageDispatcher``.
|
||||
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java#creating-props
|
||||
This way of creating the Actor is also great for integrating with Dependency Injection
|
||||
(DI) frameworks like Guice or Spring.
|
||||
|
||||
|
||||
UntypedActor API
|
||||
|
|
@ -119,7 +126,7 @@ In addition, it offers:
|
|||
The remaining visible methods are user-overridable life-cycle hooks which are
|
||||
described in the following:
|
||||
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java#lifecycle-callbacks
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java#lifecycle-callbacks
|
||||
|
||||
The implementations shown above are the defaults provided by the :class:`UntypedActor`
|
||||
class.
|
||||
|
|
@ -152,7 +159,7 @@ processing a message. This restart involves the hooks mentioned above:
|
|||
message, e.g. when a supervisor does not trap the exception and is restarted
|
||||
in turn by its supervisor. This method is the best place for cleaning up,
|
||||
preparing hand-over to the fresh actor instance, etc.
|
||||
By default it calls :meth:`postStop`.
|
||||
By default it stops all children and calls :meth:`postStop`.
|
||||
2. The initial factory from the ``actorOf`` call is used
|
||||
to produce the fresh instance.
|
||||
3. The new actor’s :meth:`postRestart` method is invoked with the exception
|
||||
|
|
@ -162,7 +169,7 @@ processing a message. This restart involves the hooks mentioned above:
|
|||
|
||||
An actor restart replaces only the actual actor object; the contents of the
|
||||
mailbox and the hotswap stack are unaffected by the restart, so processing of
|
||||
messages will resume after the :meth:`postRestart` hook returns. The message
|
||||
messages will resume after the :meth:`postRestart` hook returns. The message
|
||||
that triggered the exception will not be received again. Any message
|
||||
sent to an actor while it is being restarted will be queued to its mailbox as
|
||||
usual.
|
||||
|
|
@ -172,9 +179,9 @@ Stop Hook
|
|||
|
||||
After stopping an actor, its :meth:`postStop` hook is called, which may be used
|
||||
e.g. for deregistering this actor from other services. This hook is guaranteed
|
||||
to run after message queuing has been disabled for this actor, i.e. messages
|
||||
sent to a stopped actor will be redirected to the :obj:`deadLetters` of the
|
||||
:obj:`ActorSystem`.
|
||||
to run after message queuing has been disabled for this actor, i.e. messages
|
||||
sent to a stopped actor will be redirected to the :obj:`deadLetters` of the
|
||||
:obj:`ActorSystem`.
|
||||
|
||||
|
||||
Identifying Actors
|
||||
|
|
@ -188,7 +195,7 @@ Messages and immutability
|
|||
|
||||
**IMPORTANT**: Messages can be any kind of object but have to be
|
||||
immutable. Akka can’t enforce immutability (yet) so this has to be by
|
||||
convention.
|
||||
convention.
|
||||
|
||||
Here is an example of an immutable message:
|
||||
|
||||
|
|
@ -207,8 +214,8 @@ Messages are sent to an Actor through one of the following methods.
|
|||
|
||||
Message ordering is guaranteed on a per-sender basis.
|
||||
|
||||
In all these methods you have the option of passing along your own ``ActorRef``.
|
||||
Make it a practice of doing so because it will allow the receiver actors to be able to respond
|
||||
In all these methods you have the option of passing along your own ``ActorRef``.
|
||||
Make it a practice of doing so because it will allow the receiver actors to be able to respond
|
||||
to your message, since the sender reference is sent along with the message.
|
||||
|
||||
Tell: Fire-forget
|
||||
|
|
@ -229,7 +236,7 @@ to reply to the original sender, by using ``getSender().tell(replyMsg)``.
|
|||
|
||||
actor.tell("Hello", getSelf());
|
||||
|
||||
If invoked without the sender parameter the sender will be
|
||||
If invoked without the sender parameter the sender will be
|
||||
:obj:`deadLetters` actor reference in the target actor.
|
||||
|
||||
Ask: Send-And-Receive-Future
|
||||
|
|
@ -244,13 +251,13 @@ will immediately return a :class:`Future`:
|
|||
Future future = actorRef.ask("Hello", timeoutMillis);
|
||||
|
||||
The receiving actor should reply to this message, which will complete the
|
||||
future with the reply message as value; ``getSender.tell(result)``.
|
||||
future with the reply message as value; ``getSender.tell(result)``.
|
||||
|
||||
To complete the future with an exception you need send a Failure message to the sender.
|
||||
This is not done automatically when an actor throws an exception while processing a
|
||||
message.
|
||||
To complete the future with an exception you need send a Failure message to the sender.
|
||||
This is not done automatically when an actor throws an exception while processing a
|
||||
message.
|
||||
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java#reply-exception
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java#reply-exception
|
||||
|
||||
If the actor does not complete the future, it will expire after the timeout period,
|
||||
specified as parameter to the ``ask`` method.
|
||||
|
|
@ -258,16 +265,16 @@ specified as parameter to the ``ask`` method.
|
|||
See :ref:`futures-java` for more information on how to await or query a
|
||||
future.
|
||||
|
||||
The ``onComplete``, ``onResult``, or ``onTimeout`` methods of the ``Future`` can be
|
||||
used to register a callback to get a notification when the Future completes.
|
||||
The ``onComplete``, ``onResult``, or ``onTimeout`` methods of the ``Future`` can be
|
||||
used to register a callback to get a notification when the Future completes.
|
||||
Gives you a way to avoid blocking.
|
||||
|
||||
.. warning::
|
||||
|
||||
When using future callbacks, inside actors you need to carefully avoid closing over
|
||||
the containing actor’s reference, i.e. do not call methods or access mutable state
|
||||
on the enclosing actor from within the callback. This would break the actor
|
||||
encapsulation and may introduce synchronization bugs and race conditions because
|
||||
the containing actor’s reference, i.e. do not call methods or access mutable state
|
||||
on the enclosing actor from within the callback. This would break the actor
|
||||
encapsulation and may introduce synchronization bugs and race conditions because
|
||||
the callback will be scheduled concurrently to the enclosing actor. Unfortunately
|
||||
there is not yet a way to detect these illegal accesses at compile time. See also:
|
||||
:ref:`jmm-shared-state`
|
||||
|
|
@ -278,7 +285,7 @@ even if that entails waiting for it (but keep in mind that waiting inside an
|
|||
actor is prone to dead-locks, e.g. if obtaining the result depends on
|
||||
processing another message on this actor).
|
||||
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java
|
||||
:include: import-future,using-ask
|
||||
|
||||
Forward message
|
||||
|
|
@ -297,7 +304,7 @@ You need to pass along your context variable as well.
|
|||
Receive messages
|
||||
================
|
||||
|
||||
When an actor receives a message it is passed into the ``onReceive`` method, this is
|
||||
When an actor receives a message it is passed into the ``onReceive`` method, this is
|
||||
an abstract method on the ``UntypedActor`` base class that needs to be defined.
|
||||
|
||||
Here is an example:
|
||||
|
|
@ -340,17 +347,15 @@ message.
|
|||
Stopping actors
|
||||
===============
|
||||
|
||||
Actors are stopped by invoking the ``stop`` method of the ``ActorRef``.
|
||||
The actual termination of the actor is performed asynchronously, i.e.
|
||||
``stop`` may return before the actor is stopped.
|
||||
Actors are stopped by invoking the :meth:`stop` method of a ``ActorRefFactory``,
|
||||
i.e. ``ActorContext`` or ``ActorSystem``. Typically the context is used for stopping
|
||||
child actors and the system for stopping top level actors. The actual termination of
|
||||
the actor is performed asynchronously, i.e. :meth:`stop` may return before the actor is
|
||||
stopped.
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
actor.stop();
|
||||
|
||||
Processing of the current message, if any, will continue before the actor is stopped,
|
||||
Processing of the current message, if any, will continue before the actor is stopped,
|
||||
but additional messages in the mailbox will not be processed. By default these
|
||||
messages are sent to the :obj:`deadLetters` of the :obj:`ActorSystem`, but that
|
||||
messages are sent to the :obj:`deadLetters` of the :obj:`ActorSystem`, but that
|
||||
depends on the mailbox implementation.
|
||||
|
||||
When stop is called then a call to the ``def postStop`` callback method will
|
||||
|
|
@ -365,7 +370,7 @@ take place. The ``Actor`` can use this callback to implement shutdown behavior.
|
|||
|
||||
All Actors are stopped when the ``ActorSystem`` is stopped.
|
||||
Supervised actors are stopped when the supervisor is stopped, i.e. children are stopped
|
||||
when parent is stopped.
|
||||
when parent is stopped.
|
||||
|
||||
|
||||
PoisonPill
|
||||
|
|
@ -381,7 +386,7 @@ If the ``PoisonPill`` was sent with ``ask``, the ``Future`` will be completed wi
|
|||
|
||||
Use it like this:
|
||||
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java
|
||||
:include: import-actors,poison-pill
|
||||
|
||||
.. _UntypedActor.HotSwap:
|
||||
|
|
@ -402,10 +407,10 @@ The hotswapped code is kept in a Stack which can be pushed and popped.
|
|||
|
||||
To hotswap the Actor using ``getContext().become``:
|
||||
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java
|
||||
:include: import-procedure,hot-swap-actor
|
||||
|
||||
The ``become`` method is useful for many different things, such as to implement
|
||||
The ``become`` method is useful for many different things, such as to implement
|
||||
a Finite State Machine (FSM).
|
||||
|
||||
Here is another little cute example of ``become`` and ``unbecome`` in action:
|
||||
|
|
@ -432,7 +437,7 @@ through regular supervisor semantics.
|
|||
|
||||
Use it like this:
|
||||
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java
|
||||
:include: import-actors,kill
|
||||
|
||||
Actors and exceptions
|
||||
|
|
@ -462,9 +467,9 @@ messages on that mailbox, will be there as well.
|
|||
What happens to the actor
|
||||
-------------------------
|
||||
|
||||
If an exception is thrown, the actor instance is discarded and a new instance is
|
||||
If an exception is thrown, the actor instance is discarded and a new instance is
|
||||
created. This new instance will now be used in the actor references to this actor
|
||||
(so this is done invisible to the developer). Note that this means that current
|
||||
state of the failing actor instance is lost if you don't store and restore it in
|
||||
``preRestart`` and ``postRestart`` callbacks.
|
||||
(so this is done invisible to the developer). Note that this means that current
|
||||
state of the failing actor instance is lost if you don't store and restore it in
|
||||
``preRestart`` and ``postRestart`` callbacks.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue