Parallele Programmierung (3IB)
Aktoren überwachen andere Aktoren (solche “Überwacher” heißen supersivor).
Statt “defensive programming” oder Exception Handling: “let it crash”:
Aktoren (Supervisor) überwachen Aktoren (Worker oder Supervisor)
3record Greeting(String from) {}
1public class DemoMessagesActor extends AbstractLoggingActor {
2 @Override
public Receive createReceive() {
4 return receiveBuilder()
.match(Greeting.class, msg -> {
log().info("greeted by {}", msg.from());
})
.build();
}
}
AbstractLoggingActor
oder AbstractActor
(ohne Logging)
createReceive()
-Methode wird überschrieben
Greeting
Receive
-Objekt
public class NewActor extends AbstractActor {
@Override
public Receive createReceive() {
return receiveBuilder()
.match(Msg1.class, this::receiveMsg1)
.match(Msg2.class, this::receiveMsg2)
.match(Msg3.class, this::receiveMsg3)
.build();
}
private void receiveMsg1(Msg1 msg) {...}
private void receiveMsg2(Msg2 msg) {...}
private void receiveMsg3(Msg3 msg) {...}
}
ActorRef
ist der Basis-Typ für Aktoren in AkkaactorOf
ist Factory-Methode zum Erzeugen neuer Aktoren
Akka.system()
ist “Wurzel”-KontextProps.create(
…)
: hier Implementierungsklasse des Aktors angeben – z. B. MyActor
actorOf
ein Akka-interner Name angegeben werden, über den der Aktor identifiziert werden kannhttps://doc.akka.io/docs/akka/current/general/ActorPath.png (abgewandelt)
getSender()
: von welchem Aktor kam die letzte Nachricht (die gerade behandelt wird)?import static akka.pattern.PatternsCS.ask;
CompletableFuture<Object> future1 = ask(actorA, "request 1", 1000);
CompletableFuture<Object> future2 = ask(actorB, "request 2", 1000);
CompletableFuture<Result> transformed =
CompletableFuture.allOf(future1, future2).thenApply(v -> {
String x = (String) future1.join();
String s = (String) future2.join();
return new Result(x, s);
});
public class WatchActor extends AbstractActor {
ActorRef child = getContext().actorOf(
Props.create(ListenerActor.class), "listener");
ActorRef lastSender;
public WatchActor() {
getContext().watch(this.child);
}
@Override
public Receive createReceive() {
return receiveBuilder()
.match(PoisonPill.class, (msg) -> {
getContext().stop(this.child);
this.lastSender = getSender(); })
.match(Terminated.class, (msg) -> {
if (msg.getActor() == this.child) {
this.lastSender.tell("finished", null);
} })
.build();
}
}
Hettel und Tran (2016)
FindMsg
mit drei zu durchsuchenden Dateien trifft beim Master einWorkMsg
an ihnWorkMsg
und sendet Ergebnisse als ResultMsg
an Master zurückResultMsg
und schickt sie an den Listenerpp.11.01-FindWords
akka.routing.*
>> RoundRobinRoutingLogic
RandomRoutingLogic
SmallestMailboxRoutingLogic
BroadcastRoutingLogic
ScatterGatherFirstCompletedRoutingLogic
TailChoppingRoutingLogic
ConsistentHashingRoutingLogic
Allen (2013, 4)
akka.routing.*
RoundRobinRoutingLogic
>> RandomRoutingLogic
SmallestMailboxRoutingLogic
BroadcastRoutingLogic
ScatterGatherFirstCompletedRoutingLogic
TailChoppingRoutingLogic
ConsistentHashingRoutingLogic
Allen (2013, 3)
akka.routing.*
RoundRobinRoutingLogic
RandomRoutingLogic
>> SmallestMailboxRoutingLogic
BroadcastRoutingLogic
ScatterGatherFirstCompletedRoutingLogic
TailChoppingRoutingLogic
ConsistentHashingRoutingLogic
Allen (2013, 5)
akka.routing.*
RoundRobinRoutingLogic
RandomRoutingLogic
SmallestMailboxRoutingLogic
>> BroadcastRoutingLogic
ScatterGatherFirstCompletedRoutingLogic
TailChoppingRoutingLogic
ConsistentHashingRoutingLogic
Allen (2013, 6)
akka.routing.*
RoundRobinRoutingLogic
RandomRoutingLogic
SmallestMailboxRoutingLogic
BroadcastRoutingLogic
>> ScatterGatherFirstCompletedRoutingLogic
TailChoppingRoutingLogic
ConsistentHashingRoutingLogic
Allen (2013, 7)
var routees = new ArrayList<Routee>();
for (var i = 0; i < 5; i++) {
var routee = getContext().actorOf(Props.create(Worker.class));
getContext().watch(routee);
routees.add(new ActorRefRoutee(routee));
}
var router = new Router(new RoundRobinRoutingLogic(), routees);
// ...
router.route(message, getSelf());
Hettel und Tran (2016)
FindMsg
kommt beim Master anWorkMsg
an den Router geschickt.WorkMsg
an w1 und w2WorkMsg
geht vom Router wieder wegen Round Robin-Logik an w1ResultMsg
ein und sendet Gesamtergebnis als ResultMsg
an Listenerpp.11.02-RouterFindWords
Im Fall einer Router-Group sind Router und Routees weniger eng gekoppelt:
Im Fall eines Router-Pools sind Router und Routees enger gekoppelt als bei einer Gruppe: