SlideShare ist ein Scribd-Unternehmen logo
1 von 97
Scaling Up and Out with Actors St. Louis Java Users Group June 9 th , 2011 Tim Dalton Senior Software Engineer Object Computing Inc.
Actors ?
What are actors? ,[object Object],[object Object]
Nothing to synchronize ,[object Object]
Actors have a mailbox / queue for messages
Where does it come from ? ,[object Object]
Popularized by Erlang OTP (Open Telecom Platform)
Message passing closer to the original intent for Object Orientation ,[object Object]
“ OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things”
Why actors ? Because  this:
Became this
Became this Will soon become ...
THIS
Sometimes this is needed
Not a silver bullet...
… or pixie dust
Another tool in our “Concurrency Toolbox”
What is Akka? ,[object Object]
AspectWerkz
JRockit
Terracotta
Typesafe  ,[object Object],Named project “Akka” after mountains in Sweden Viktor Klang Speaking at Strange Loop 2011 !
Why Akka? ,[object Object]
A simple actor import akka.actor.UntypedActor; public class ToStringActor extends UntypedActor { @Override public void onReceive(Object message) { System.out.println(message.toString()); } }
A simple actor import akka.actor.{Actor} class ToStringActor extends Actor { override def receive = {  case message:Any =>    println(message.toString)  } }
Nothing prevents this  (ns tfd.clojurefun.ClojureActor (:gen-class :extends akka.actor.UntypedActor ) ) (defn -onReceive [this msg] (println (.toString msg)) )
Sending messages ActorRef toString =  Actors.actorOf(ToStringActor.class). start (); toString.sendOneWay(42); 42 toString.sendOneWay(3.14159); 3.14159 toString.sendOneWay(true); true
Sending messages val toString =  Actor.actorOf(classOf[ToStringActor]).start toString ! 42 // same as toString.!(42) 42 ToString ! 3.14159 3.14159 toString ! true ,[object Object]
Replying to messages public class DoubleItActor extends UntypedActor { @Override public void onReceive(Object message) {   getContext(). replyUnsafe ( message.toString() + message.toString()); } } Or: getContext(). replySafe (
Replying to messages class DoubleItActor extends Actor { override def receive = { case message:Any =>  self. reply ( message.toString + message.toString)  } } Or: self. reply_?
Send with reply ActorRef doubleIt =  Actors.actorOf(DoubleItActor.class).start(); System.out.println( doubleIt.sendRequestReply("foo")); foofoo System.out.println( doubleIt.sendRequestReplyFuture("bar") .get()); barbar System.out.println( doubleIt.sendRequestReplyFuture("bar") .await().result()); Some(barbar)
Send with reply val doubleIt =  Actors.actorOf(classOf[DoubleItActor]).start println(doubleIt !! "foo") Some(foofoo) println((doubleIt !!! "bar").get) barbar println((doubleIt !!! "bar").await.result) Some(barbar) println((doubleIt !!! "meh") .map((x:String) => x.length).await.result) Some(6)
Less painful in Java 8 ? System.out.println( doubleIt.sendRequestReplyFuture(&quot;meh&quot;) .map(new Function<String,Integer>() { public Integer apply(String param) { return param.length(); } }).await().result()); Some(6)
Futures in Akka 1.1 val upperIt = actorOf(classOf[ToUpperActor]).start val doubleFoo = doubleIt !!! &quot;foo&quot; val upperBar = upperIt !!! &quot;bar&quot; println( (for ( x:String <- doubleFoo; y:String <- upperBar ) yield (x + y)).await.result ) Some(foofooBAR)
What if one way message is replied to? ActorRef toString = actorOf(ToStringActor.class) .start(); doubleIt.sendOneWay(&quot;foobar&quot;, toString); foobarfoobar ,[object Object],foobarfoobar
Anonymous actors val fooActor = Actor.actorOf( new Actor {  def receive = {  case x => println(&quot;Foo: &quot; + x)  }  }).start
Anonymous actors Unfortunately this does not work: ActorRef act = Actors.actorOf(new UntypedActor() { public void onReceive(Object message) { System.out.println(&quot;Received : &quot; + message); } }).start();
Anonymous actors A factory is needed: ActorRef act = actorOf(new UntypedActorFactory() { public UntypedActor create() { return new UntypedActor() { public void onReceive(Object message) { System.out.println(&quot;Received : &quot;  + message); } }; } }).start();
No built-in pattern matching in Java (Author's idea, not part of Akka) public void onReceive(Object message) { Matchable matchable = new Matchable(message); for (Integer value :  matchable.matchesInteger(equalTo(42))) { System.out.println(value + &quot; is the answer !&quot;); } for (Integer value : matchable.matchesInteger()) { System.out.println(value +  &quot; is a number, but not the answer.&quot;); } for (Object value : matchable) { System.out.println(value + &quot; is not even close.&quot;); } } - Matchable is an Iterable that can only be iterated once - Idea inspired similar idea in Play! framework - Uses Hamcrest matchers
Scala equivalent def receive = { case value:Integer if (value == 42) =>    println(value + &quot; is the answer !&quot;) case value:Integer =>   println(value +    &quot; is a number, but not the answer.&quot;) case value:Any => println(value + &quot; is not even close.&quot;) }
Typed actors public interface Counter { public void increment(); public Integer getValue(); public Future<Integer> getFutureValue(); }
Typed actors public class CounterActor extends TypedActor  implements Counter { private Integer value = 0; public void increment() { try { Thread.sleep(1000); }  catch (InterruptedException ex) { } value++; } public Integer getValue() { return value; } public Future<Integer> getFutureValue() { return future(value); } }
Typed actors Counter counter = TypedActor .newInstance(Counter.class,    CounterActor.class, 2000); counter.increment(); System.out.println(counter.getValue()); 1 counter.increment(); System.out.println( counter.getFutureValue().get()); 2
Server managed remote actors On Remote Server: RemoteServerModule server =   remote().start(&quot;localhost&quot;, 2553); server.register(&quot;double-it&quot;,  actorOf(DoubleItActor.class)); server.register(&quot;to-string&quot;,  actorOf(ToStringActor.class)); On Client: ActorRef doubleIt = remote() .actorFor(&quot;double-it&quot;, &quot;localhost&quot;, 2553); ActorRef toString = remote() .actorFor(&quot;to-string&quot;, &quot;localhost&quot;, 2553); doubleIt.sendOneWay(&quot;meh&quot;, toString); On Remote Server: mehmeh
Client managed remote actors ActorRef remoteToString = remote().actorOf( ToStringActor.class, &quot;localhost&quot;, 2553).start(); ActorRef localDoubleIt =    Actors.actorOf(DoubleItActor.class).start(); remoteToString.sendOneWay(&quot;foo&quot;); localDoubleIt.sendOneWay(&quot;bar&quot;, remoteToString); On Remote Server: foo barbar Deprecated as of Akka 1.1
Event based dispatching ,[object Object]
Actors should not block
Akka can spawn extra threads if needed ,[object Object]
Priority event based dispatcher val act = actorOf(new Actor {  def receive = { case x => println(&quot;Received : &quot; + x) }}) act.dispatcher =   new PriorityExecutorBasedEventDrivenDispatcher(&quot;foo&quot;, PriorityGenerator { case _:String => 0 case x:Int => x case _ => 50 }) act.start.dispatcher.suspend(act) act ! 1.0 act ! &quot;foo&quot; (0 to 9).map { x:Int => act ! (x * 10) } act ! 2.0 act ! &quot;bar&quot;
Priority event based dispatcher Received : foo Received : 0 Received : bar Received : 10 Received : 20 Received : 30 Received : 40 Received : 1.0 Received : 50 Received : 2.0 Received : 60 Received : 70 Received : 80 Received : 90
Work stealing event dispatcher public class FooActor extends UntypedActor { public static MessageDispatcher dispatcher = Dispatchers .newExecutorBasedEventDrivenWorkStealingDispatcher(&quot;foobar&quot;, 5) .build(); private static int currentId = 0; private final int instanceId; private int count = 0; public FooActor() { getContext().setDispatcher(dispatcher); instanceId = currentId++; }
Work stealing event dispatcher @Override public void onReceive(Object message) { System.out.printf( &quot;Foo %d processed : %s (count = %d) on Thread : %s&quot;,   InstanceId,   message.toString(),   ++count,   Thread.currentThread().getName() ); try { Thread.sleep(instanceId * 50 + 50); }  catch (InterruptedException ex) {  } }
Foo 0 processed : 0 (count = 1) on Thread : akka:event-driven:dispatcher:foobar-1 Foo 1 processed : 1 (count = 1) on Thread : akka:event-driven:dispatcher:foobar-2 Foo 0 processed : 2 (count = 2) on Thread : akka:event-driven:dispatcher:foobar-3 Foo 1 processed : 3 (count = 2) on Thread : akka:event-driven:dispatcher:foobar-4 Foo 0 processed : 4 (count = 3) on Thread : akka:event-driven:dispatcher:foobar-5 Foo 1 processed : 5 (count = 3) on Thread : akka:event-driven:dispatcher:foobar-6 Foo 0 processed : 6 (count = 4) on Thread : akka:event-driven:dispatcher:foobar-7 Foo 0 processed : 7 (count = 5) on Thread : akka:event-driven:dispatcher:foobar-8 Foo 1 processed : 8 (count = 4) on Thread : akka:event-driven:dispatcher:foobar-9 Foo 0 processed : 9 (count = 6) on Thread : akka:event-driven:dispatcher:foobar-10
Foo 1 processed : 93 (count = 40) on Thread : akka:event-driven:dispatcher:foobar-15 Foo 0 processed : 94 (count = 55) on Thread : akka:event-driven:dispatcher:foobar-13 Foo 0 processed : 95 (count = 56) on Thread : akka:event-driven:dispatcher:foobar-13 Foo 0 processed : 96 (count = 57) on Thread : akka:event-driven:dispatcher:foobar-16 Foo 1 processed : 97 (count = 41) on Thread : akka:event-driven:dispatcher:foobar-14 Foo 0 processed : 98 (count = 58) on Thread : akka:event-driven:dispatcher:foobar-4 Foo 1 processed : 99 (count = 42) on Thread : akka:event-driven:dispatcher:foobar-4
Thread based dispatcher getContext().setDispatcher( Dispatchers.newThreadBasedDispatcher(getContext()));. self.dispatcher =  Dispatchers.newThreadBasedDispatcher(self) ,[object Object]
Good for “daemon” actors ,[object Object]
Blocking
Routing and load balancing InfiniteIterator<ActorRef> iter =  new CyclicIterator<ActorRef>(Arrays.asList( actorOf(FooActor.class).start(), actorOf(BarActor.class).start() )); for (Integer value:Arrays.asList(4, 8, 15, 16, 23, 42)) { iter.next().sendOneWay(value); } Bar: 8 Foo: 4 Bar: 16 Foo: 15 Bar: 42 Foo: 23
Routing and load balancing ActorRef router = actorOf(new UntypedActorFactory() { public UntypedActor create() { return new UntypedLoadBalancer() { private InfiniteIterator iterator =  new CyclicIterator<ActorRef>(Arrays.asList( actorOf(FooActor.class).start(), actorOf(BarActor.class).start())); public InfiniteIterator<ActorRef> seq() { return iterator; } }; }}).start();  for (Integer value :  Arrays.asList(4, 8, 15, 16, 23, 42)) { router.sendOneWay(value); }
Routing and load balancing class SleepyCounterActor(name:String, sleepyTime:Int)  extends Actor  { var count = 0 def receive = {    case x => { Thread.sleep(sleepyTime)   count += 1;  printf(&quot;%s received '%s' count = %d&quot;,   name, x, count) } }
Routing and load balancing val iter = new  SmallestMailboxFirstIterator(List( actorOf(new SleepyCounterActor(&quot;Foo&quot;,  1)).start,   actorOf(new SleepyCounterActor(&quot;Bar&quot;, 50)).start)) (1 to 15).foreach { x:Int => Thread.sleep(2) iter.next ! x }
Routing and load balancing val balancer =  loadBalancerActor (new SmallestMailboxFirstIterator(List( actorOf(new SleepyCounterActor(&quot;Foo&quot;, 1)).start, actorOf(new SleepyCounterActor(&quot;Bar&quot;, 50)).start) ) ) (1 to 15).foreach { x:Int => Thread.sleep(2) balancer ! x }
Routing and Load Balancing Foo received '3' count = 1 Foo received '4' count = 2 Foo received '6' count = 3 Foo received '8' count = 4 Foo received '9' count = 5 Foo received '10' count = 6 Foo received '11' count = 7 Foo received '12' count = 8 Foo received '13' count = 9 Foo received '14' count = 10 Foo received '15' count = 11 Bar received '1' count = 1 Bar received '2' count = 2 Bar received '5' count = 3 Bar received '7' count = 4
Supervision and fault tolerance class DivideInto10Actor extends Actor { def receive = { case x:Int =>  self.reply_?(10 / x) } override def preStart { print(&quot;DivideInto10Actor.preStart()&quot;) } override def postStop { print(&quot;DivideInto10Actor.postStop()&quot;) } override def preRestart(reason: Throwable) { printf(&quot;DivideInto10Actor.preRestart(%s)&quot;, reason.getMessage) } override def postRestart(reason: Throwable) { printf(&quot;DivideInto10Actor.postRestart(%s)&quot;, reason.getMessage) } }
Supervision and fault tolerance val supervisedActors = Array( actorOf(classOf[DivideInto10Actor]), actorOf(classOf[DivideInto10Actor]) ) val supervisor =  Supervisor( SupervisorConfig( OneForOneStrategy(List(classOf[Exception]), 3, 1000), List( Supervise(supervisedActors(0), Permanent), Supervise(supervisedActors(1), Temporary) ))) DivideInto10Actor.preStart() DivideInto10Actor.preStart()
Supervision and fault tolerance supervisedActors(0) ! 0 // Permanent  DivideInto10Actor.postStop() java.lang.ArithmeticException: / by zero ... DivideInto10Actor.preRestart(/ by zero) DivideInto10Actor.preStart() DivideInto10Actor.postRestart(/ by zero) supervisedActors(1) ! 0 // Temporary   DivideInto10Actor.postStop() java.lang.ArithmeticException: / by zero ... DivideInto10Actor.preRestart(/ by zero) DivideInto10Actor.preStart() DivideInto10Actor.postRestart(/ by zero)
Supervision and fault tolerance With OneForOneStrategy: SupervisedActors(0) ! 0 // Permanent  DivideInto10Actor.preRestart(/ by zero) java.lang.ArithmeticException: / by zero ... DivideInto10Actor.preStart() DivideInto10Actor.postRestart(/ by zero) SupervisedActors(1) ! 0 // Temporary   DivideInto10Actor.postStop() java.lang.ArithmeticException: / by zero
Supervision and fault tolerance val supervisor =  Supervisor( SupervisorConfig( OneForOneStrategy(List(classOf[Exception]), 3, 1000), Nil )) supervisedActors(0).setLifeCycle(Permanent) supervisedActors(0).start supervisor.link(supervisedActors(0)) supervisedActors(1).setLifeCycle(Temporary) supervisedActors(1).start supervisor.link(supervisedActors(1))
Supervision and fault tolerance val supervisor =  Supervisor( SupervisorConfig( OneForOneStrategy(List(classOf[Exception]), 3, 1000), Nil )) supervisedActors(0).setLifeCycle(Permanent) supervisor.startLink(supervisedActors(0)) supervisedActors(1).setLifeCycle(Temporary) supervisor.startLink(supervisedActors(1))
Supervision and fault tolerance class CustomSupervisor extends Actor { self.faultHandler = OneForOneStrategy( List(classOf[Throwable]), 5, 5000) def receive = { case x => println(&quot;CustomSupervisor received : &quot; + x) } } val supervisor = actorOf(classOf[CustomSupervisor]).start supervisedActors(0).setLifeCycle(Permanent) supervisor.startLink(supervisedActors(0)) supervisedActors(1).setLifeCycle(Temporary) supervisor.startLink(supervisedActors(1))
Scheduler Scheduler.schedule( receiverActor,  messageToBeSent, initialDelayBeforeSending, delayBetweenMessages,  timeUnit) Scheduler.scheduleOne( receiverActor,  messageToBeSent, delayUntilSend, timeUnit)
Scheduler Scheduler.schedule( toString, &quot;ping&quot;, 0, 5, TimeUnit.SECONDS ); Scheduler.scheduleOnce(   toString, &quot;pong&quot;, 15, TimeUnit.SECONDS );
Declarative configuration akka.conf: akka { version = &quot;1.1&quot;  enabled-modules = [&quot;camel&quot;, &quot;http&quot;] time-unit = &quot;seconds&quot;  event-handlers = [&quot;akka.event.EventHandler$DefaultListener&quot;]  event-handler-level = &quot;INFO&quot;  ... actor { timeout = 5  serialize-messages = off  throughput = 5  ...
Declarative configuration default-dispatcher { type = &quot;GlobalExecutorBasedEventDriven&quot;  keep-alive-time = 60 core-pool-size-factor = 1.0  max-pool-size-factor  = 4.0 mailbox-capacity = -1  rejection-policy = &quot;caller-runs&quot;  throughput = 5 ...
Data Flow concurrency val x, y, z = Promise[Int] flow { z << x() + y() println(&quot;z = &quot; + z()) } flow { x << 40 } flow { y << 2 } } z = 42
Back to (the) Future val future =  Future  { Thread.sleep(1000) 42 } val doubleItActor = actorOf(new Actor { def receive = { case x:Int => Thread.sleep(1000); self.reply(x * 2) case _ => self.reply(0) } } ).start val actorReply:Future[Int] =  doubleItActor !!! 73 val promise = Promise[Int]
Back to (the) Future flow { promise << 23 } val totalFuture = for { x <- future y <- actorReply c <- promise } yield ( x + y + c ) println(totalFuture.get) 211
Back to (the) Future flow { println (future() + promise() + actorReply()) } 211
Back to (the) Future val resultList = Future. sequence ( List(future, actorReply, promise)).get println (resultList) List(42, 146, 23) println (resultList.reduce(_ + _)) 211
 
Map-Reduce (like) with Akka (finding anagrams)
Stateful behaviors val doubleIt = actorOf(classOf[DoubleItActor]) .start println(doubleIt !! &quot;foo&quot;) Some(foofoo) doubleIt ! HotSwap ( self => { case message => self.reply( message.toString + message.toString + &quot; hotswapped&quot;) }) println(doubleIt !! &quot;bar&quot;) Some(barbar hotswapped) doubleIt ! RevertHotSwap println(doubleIt !! &quot;meh&quot;) Some(mehmeh)
Stateful behaviors class FooActor extends UntypedActor { public void onReceive(Object message) { if (&quot;foo&quot;.equals(message)) { become(BAR_BEHAVIOR); } else { getContext().replySafe(&quot;foo&quot;); } }
Stateful behaviors private final Procedure<Object> BAR_BEHAVIOR = new Procedure<Object>()  { @Override public void apply(Object param) { getContext().replySafe(&quot;bar&quot;); unbecome(); } };
Stateful behaviors System.out.println(actorRef.sendRequestReply(&quot;bar&quot;)); actorRef.sendOneWay(&quot;foo&quot;); System.out.println(actorRef.sendRequestReply(&quot;bar&quot;)); System.out.println(actorRef.sendRequestReply(&quot;bar&quot;)); foo bar foo
Finite state machine in an Actor (vending machine)
Software Transactional Memory: Refs ,[object Object]
A form on optimistic locking for memory
ACI (Atomic, Consistent, Isolated) ,[object Object],[object Object]
Refs val ref1 = new Ref(4) val ref2 = new Ref(4) println(&quot;ref1 = &quot; + ref1.get) println(&quot;ref2 = &quot; + ref2.get) try { atomic { ref1.swap(12) ref2.alter(_ * 2) ref1.alter(_ / 0) } } catch { case ex:Exception => println(ex.getMessage) } println(&quot;ref1 = &quot; + ref1.get) println(&quot;ref2 = &quot; + ref2.get) ref1 = 4 ref2 = 4 / by zero ref1 = 4 ref2 = 4
Refs val ref1 = new Ref(4) val ref2 = new Ref(4) println(&quot;ref1 = &quot; + ref1.get) println(&quot;ref2 = &quot; + ref2.get) try { ref1.swap(12) ref2.alter(_ * 2) ref1.alter(_ / 0) } catch { case ex:Exception => println(ex.getMessage) } println(&quot;ref1 = &quot; + ref1.get) println(&quot;ref2 = &quot; + ref2.get) ref1 = 4 ref2 = 4 / by zero ref1 = 12 ref2 = 8
Refs final Ref<Integer> ref1 = new Ref(4); final Ref<Integer> ref2 = new Ref(4); new Atomic<Integer>() {  public Integer atomically() { ref1.set(8); ref2.set(12); return (Integer) ref1.get() +     (Integer) ref2.get(); } }.execute());
Transactional datastructues ,[object Object]
TransactionalVector ,[object Object]
Transactional datastructues val tranMap = TransactionalMap[String, Int](&quot;Foo&quot; -> 23) val tranVector = TransactionalVector(2.0, 4.0, 6.0) try { atomic { tranMap += (&quot;Bar&quot; -> 42) tranVector.add(8.0) println(tranMap) println(tranVector) 1 / 0 } } catch { case ex:Any => println(ex) } atomic { println(tranMap); println(tranVector) } Map(Bar -> 42, Foo -> 23) TransactionalVector(2.0, 4.0, 6.0, 8.0) java.lang.ArithmeticException: / by zero Map(Foo -> 23) TransactionalVector(2.0, 4.0, 6.0)
Dining Philosophers with STM
Philosopher 3 wants to ponder Philosopher 4 sees forks available Philosopher 1 sees forks available Philosopher 4 eats Philosopher 1 eats Philosopher 2 sees forks available Philosopher 2 can't get forks Philosopher 2 can't get forks Philosopher 5 can't get forks

Weitere ähnliche Inhalte

Was ist angesagt?

Important java programs(collection+file)
Important java programs(collection+file)Important java programs(collection+file)
Important java programs(collection+file)Alok Kumar
 
Executing Sql Commands
Executing Sql CommandsExecuting Sql Commands
Executing Sql Commandsleminhvuong
 
Java simple programs
Java simple programsJava simple programs
Java simple programsVEERA RAGAVAN
 
CSharp for Unity Day2
CSharp for Unity Day2CSharp for Unity Day2
CSharp for Unity Day2Duong Thanh
 
Works Applications Test - Chinmay Chauhan
Works Applications Test - Chinmay ChauhanWorks Applications Test - Chinmay Chauhan
Works Applications Test - Chinmay ChauhanChinmay Chauhan
 
Chat application in java using swing and socket programming.
Chat application in java using swing and socket programming.Chat application in java using swing and socket programming.
Chat application in java using swing and socket programming.Kuldeep Jain
 
Java PRACTICAL file
Java PRACTICAL fileJava PRACTICAL file
Java PRACTICAL fileRACHIT_GUPTA
 
Java_practical_handbook
Java_practical_handbookJava_practical_handbook
Java_practical_handbookManusha Dilan
 
Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...Mario Fusco
 
망고100 보드로 놀아보자 19
망고100 보드로 놀아보자 19망고100 보드로 놀아보자 19
망고100 보드로 놀아보자 19종인 전
 
.NET Multithreading and File I/O
.NET Multithreading and File I/O.NET Multithreading and File I/O
.NET Multithreading and File I/OJussi Pohjolainen
 

Was ist angesagt? (19)

Call Back
Call BackCall Back
Call Back
 
Important java programs(collection+file)
Important java programs(collection+file)Important java programs(collection+file)
Important java programs(collection+file)
 
Java programs
Java programsJava programs
Java programs
 
Executing Sql Commands
Executing Sql CommandsExecuting Sql Commands
Executing Sql Commands
 
Java Generics
Java GenericsJava Generics
Java Generics
 
Play image
Play imagePlay image
Play image
 
Java simple programs
Java simple programsJava simple programs
Java simple programs
 
CSharp for Unity Day2
CSharp for Unity Day2CSharp for Unity Day2
CSharp for Unity Day2
 
Works Applications Test - Chinmay Chauhan
Works Applications Test - Chinmay ChauhanWorks Applications Test - Chinmay Chauhan
Works Applications Test - Chinmay Chauhan
 
Ad java prac sol set
Ad java prac sol setAd java prac sol set
Ad java prac sol set
 
Chat application in java using swing and socket programming.
Chat application in java using swing and socket programming.Chat application in java using swing and socket programming.
Chat application in java using swing and socket programming.
 
Java PRACTICAL file
Java PRACTICAL fileJava PRACTICAL file
Java PRACTICAL file
 
Java.lang.object
Java.lang.objectJava.lang.object
Java.lang.object
 
Java practical
Java practicalJava practical
Java practical
 
Java_practical_handbook
Java_practical_handbookJava_practical_handbook
Java_practical_handbook
 
Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...
 
망고100 보드로 놀아보자 19
망고100 보드로 놀아보자 19망고100 보드로 놀아보자 19
망고100 보드로 놀아보자 19
 
.NET Multithreading and File I/O
.NET Multithreading and File I/O.NET Multithreading and File I/O
.NET Multithreading and File I/O
 
54240326 copy
54240326   copy54240326   copy
54240326 copy
 

Andere mochten auch

Растим профессионалов
Растим профессионаловРастим профессионалов
Растим профессионалов404fest
 
Catalogo Mobiliário
Catalogo MobiliárioCatalogo Mobiliário
Catalogo MobiliárioLumatek
 
Escalera State Farm Grant Slide Show
Escalera State Farm Grant Slide ShowEscalera State Farm Grant Slide Show
Escalera State Farm Grant Slide Showguest07fbc4
 
Craciun sau asa ceva
Craciun sau asa cevaCraciun sau asa ceva
Craciun sau asa cevaguest07dcc0
 
Илья Бирман – Ангстрем
Илья Бирман – АнгстремИлья Бирман – Ангстрем
Илья Бирман – Ангстрем404fest
 
Leehom Wang
Leehom WangLeehom Wang
Leehom WangJenny
 
Real numbers
Real numbersReal numbers
Real numbersAholt13
 
R de Render - Portfolio
R de Render - PortfolioR de Render - Portfolio
R de Render - PortfolioR_de_Render
 
Media APP Summit Non-Profits
Media APP Summit Non-ProfitsMedia APP Summit Non-Profits
Media APP Summit Non-ProfitsSusan Halligan
 
جدد حياتك بالصيام
جدد حياتك بالصيامجدد حياتك بالصيام
جدد حياتك بالصيامAhmad Almadani
 
Zen Coding
Zen CodingZen Coding
Zen Coding404fest
 
Cecyt 2009
Cecyt 2009Cecyt 2009
Cecyt 2009moniki
 
NEDMA14: 10 Types of Visuals to Boost Your Social Media Engagement - Bob Car...
NEDMA14: 10 Types of Visuals to Boost Your Social Media Engagement  - Bob Car...NEDMA14: 10 Types of Visuals to Boost Your Social Media Engagement  - Bob Car...
NEDMA14: 10 Types of Visuals to Boost Your Social Media Engagement - Bob Car...New England Direct Marketing Association
 

Andere mochten auch (20)

Растим профессионалов
Растим профессионаловРастим профессионалов
Растим профессионалов
 
Catalogo Mobiliário
Catalogo MobiliárioCatalogo Mobiliário
Catalogo Mobiliário
 
Escalera State Farm Grant Slide Show
Escalera State Farm Grant Slide ShowEscalera State Farm Grant Slide Show
Escalera State Farm Grant Slide Show
 
Stackato v3
Stackato v3Stackato v3
Stackato v3
 
Het Nieuwe Werken in de praktijk
Het Nieuwe Werkenin de praktijkHet Nieuwe Werkenin de praktijk
Het Nieuwe Werken in de praktijk
 
Stackato
StackatoStackato
Stackato
 
Craciun sau asa ceva
Craciun sau asa cevaCraciun sau asa ceva
Craciun sau asa ceva
 
Downtown Ferndale Property Tour
Downtown Ferndale Property TourDowntown Ferndale Property Tour
Downtown Ferndale Property Tour
 
Илья Бирман – Ангстрем
Илья Бирман – АнгстремИлья Бирман – Ангстрем
Илья Бирман – Ангстрем
 
Leehom Wang
Leehom WangLeehom Wang
Leehom Wang
 
Web20 Elearning
Web20 ElearningWeb20 Elearning
Web20 Elearning
 
Youth Olympic
Youth OlympicYouth Olympic
Youth Olympic
 
Real numbers
Real numbersReal numbers
Real numbers
 
R de Render - Portfolio
R de Render - PortfolioR de Render - Portfolio
R de Render - Portfolio
 
Media APP Summit Non-Profits
Media APP Summit Non-ProfitsMedia APP Summit Non-Profits
Media APP Summit Non-Profits
 
جدد حياتك بالصيام
جدد حياتك بالصيامجدد حياتك بالصيام
جدد حياتك بالصيام
 
Zen Coding
Zen CodingZen Coding
Zen Coding
 
Cecyt 2009
Cecyt 2009Cecyt 2009
Cecyt 2009
 
NEDMA14: Creating Email Awesomeness! - Nirmal Parikh
NEDMA14: Creating Email Awesomeness! - Nirmal ParikhNEDMA14: Creating Email Awesomeness! - Nirmal Parikh
NEDMA14: Creating Email Awesomeness! - Nirmal Parikh
 
NEDMA14: 10 Types of Visuals to Boost Your Social Media Engagement - Bob Car...
NEDMA14: 10 Types of Visuals to Boost Your Social Media Engagement  - Bob Car...NEDMA14: 10 Types of Visuals to Boost Your Social Media Engagement  - Bob Car...
NEDMA14: 10 Types of Visuals to Boost Your Social Media Engagement - Bob Car...
 

Ähnlich wie Akka

Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STMConcurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STMMario Fusco
 
Scalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsScalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsJohn De Goes
 
Concurrency on the JVM
Concurrency on the JVMConcurrency on the JVM
Concurrency on the JVMVaclav Pech
 
Actor based approach in practice for Swift developers
Actor based approach in practice for Swift developersActor based approach in practice for Swift developers
Actor based approach in practice for Swift developersBartosz Polaczyk
 
Category theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) DataCategory theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) Datagreenwop
 
Akka.NET streams and reactive streams
Akka.NET streams and reactive streamsAkka.NET streams and reactive streams
Akka.NET streams and reactive streamsBartosz Sypytkowski
 
JavaScript Functions
JavaScript FunctionsJavaScript Functions
JavaScript FunctionsBrian Moschel
 
Hi, I need some one to help me with Design a client-server Chat so.pdf
Hi, I need some one to help me with Design a client-server Chat so.pdfHi, I need some one to help me with Design a client-server Chat so.pdf
Hi, I need some one to help me with Design a client-server Chat so.pdffashiongallery1
 
MultiClient chatting berbasis gambar
MultiClient chatting berbasis gambarMultiClient chatting berbasis gambar
MultiClient chatting berbasis gambaryoyomay93
 
Multi client
Multi clientMulti client
Multi clientganteng8
 
Laporan multiclient chatting berbasis grafis (gambar)
Laporan multiclient chatting berbasis grafis (gambar)Laporan multiclient chatting berbasis grafis (gambar)
Laporan multiclient chatting berbasis grafis (gambar)Rara Ariesta
 
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014Matthias Noback
 
2. Design patterns. part #2
2. Design patterns. part #22. Design patterns. part #2
2. Design patterns. part #2Leonid Maslov
 
RxJava и Android. Плюсы, минусы, подводные камни
RxJava и Android. Плюсы, минусы, подводные камниRxJava и Android. Плюсы, минусы, подводные камни
RxJava и Android. Плюсы, минусы, подводные камниStfalcon Meetups
 
Pick up the low-hanging concurrency fruit
Pick up the low-hanging concurrency fruitPick up the low-hanging concurrency fruit
Pick up the low-hanging concurrency fruitVaclav Pech
 

Ähnlich wie Akka (20)

Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STMConcurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
 
Scalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsScalaz 8 vs Akka Actors
Scalaz 8 vs Akka Actors
 
Concurrency on the JVM
Concurrency on the JVMConcurrency on the JVM
Concurrency on the JVM
 
Actor based approach in practice for Swift developers
Actor based approach in practice for Swift developersActor based approach in practice for Swift developers
Actor based approach in practice for Swift developers
 
Akka Testkit Patterns
Akka Testkit PatternsAkka Testkit Patterns
Akka Testkit Patterns
 
Category theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) DataCategory theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) Data
 
.NET F# Events
.NET F# Events.NET F# Events
.NET F# Events
 
Akka.NET streams and reactive streams
Akka.NET streams and reactive streamsAkka.NET streams and reactive streams
Akka.NET streams and reactive streams
 
JavaScript Functions
JavaScript FunctionsJavaScript Functions
JavaScript Functions
 
Hi, I need some one to help me with Design a client-server Chat so.pdf
Hi, I need some one to help me with Design a client-server Chat so.pdfHi, I need some one to help me with Design a client-server Chat so.pdf
Hi, I need some one to help me with Design a client-server Chat so.pdf
 
MultiClient chatting berbasis gambar
MultiClient chatting berbasis gambarMultiClient chatting berbasis gambar
MultiClient chatting berbasis gambar
 
Current State of Coroutines
Current State of CoroutinesCurrent State of Coroutines
Current State of Coroutines
 
TechTalk - Dotnet
TechTalk - DotnetTechTalk - Dotnet
TechTalk - Dotnet
 
Multi client
Multi clientMulti client
Multi client
 
2 презентация rx java+android
2 презентация rx java+android2 презентация rx java+android
2 презентация rx java+android
 
Laporan multiclient chatting berbasis grafis (gambar)
Laporan multiclient chatting berbasis grafis (gambar)Laporan multiclient chatting berbasis grafis (gambar)
Laporan multiclient chatting berbasis grafis (gambar)
 
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
 
2. Design patterns. part #2
2. Design patterns. part #22. Design patterns. part #2
2. Design patterns. part #2
 
RxJava и Android. Плюсы, минусы, подводные камни
RxJava и Android. Плюсы, минусы, подводные камниRxJava и Android. Плюсы, минусы, подводные камни
RxJava и Android. Плюсы, минусы, подводные камни
 
Pick up the low-hanging concurrency fruit
Pick up the low-hanging concurrency fruitPick up the low-hanging concurrency fruit
Pick up the low-hanging concurrency fruit
 

Kürzlich hochgeladen

Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxGenerative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxfnnc6jmgwh
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Nikki Chapple
 
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...itnewsafrica
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integrationmarketing932765
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Kaya Weers
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observabilityitnewsafrica
 

Kürzlich hochgeladen (20)

Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxGenerative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
 
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
 

Akka

  • 1. Scaling Up and Out with Actors St. Louis Java Users Group June 9 th , 2011 Tim Dalton Senior Software Engineer Object Computing Inc.
  • 3.
  • 4.
  • 5. Actors have a mailbox / queue for messages
  • 6.
  • 7. Popularized by Erlang OTP (Open Telecom Platform)
  • 8.
  • 9. “ OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things”
  • 10. Why actors ? Because this:
  • 12. Became this Will soon become ...
  • 13. THIS
  • 15. Not a silver bullet...
  • 16. … or pixie dust
  • 17. Another tool in our “Concurrency Toolbox”
  • 18.
  • 22.
  • 23.
  • 24. A simple actor import akka.actor.UntypedActor; public class ToStringActor extends UntypedActor { @Override public void onReceive(Object message) { System.out.println(message.toString()); } }
  • 25. A simple actor import akka.actor.{Actor} class ToStringActor extends Actor { override def receive = { case message:Any => println(message.toString) } }
  • 26. Nothing prevents this (ns tfd.clojurefun.ClojureActor (:gen-class :extends akka.actor.UntypedActor ) ) (defn -onReceive [this msg] (println (.toString msg)) )
  • 27. Sending messages ActorRef toString = Actors.actorOf(ToStringActor.class). start (); toString.sendOneWay(42); 42 toString.sendOneWay(3.14159); 3.14159 toString.sendOneWay(true); true
  • 28.
  • 29. Replying to messages public class DoubleItActor extends UntypedActor { @Override public void onReceive(Object message) { getContext(). replyUnsafe ( message.toString() + message.toString()); } } Or: getContext(). replySafe (
  • 30. Replying to messages class DoubleItActor extends Actor { override def receive = { case message:Any => self. reply ( message.toString + message.toString) } } Or: self. reply_?
  • 31. Send with reply ActorRef doubleIt = Actors.actorOf(DoubleItActor.class).start(); System.out.println( doubleIt.sendRequestReply(&quot;foo&quot;)); foofoo System.out.println( doubleIt.sendRequestReplyFuture(&quot;bar&quot;) .get()); barbar System.out.println( doubleIt.sendRequestReplyFuture(&quot;bar&quot;) .await().result()); Some(barbar)
  • 32. Send with reply val doubleIt = Actors.actorOf(classOf[DoubleItActor]).start println(doubleIt !! &quot;foo&quot;) Some(foofoo) println((doubleIt !!! &quot;bar&quot;).get) barbar println((doubleIt !!! &quot;bar&quot;).await.result) Some(barbar) println((doubleIt !!! &quot;meh&quot;) .map((x:String) => x.length).await.result) Some(6)
  • 33. Less painful in Java 8 ? System.out.println( doubleIt.sendRequestReplyFuture(&quot;meh&quot;) .map(new Function<String,Integer>() { public Integer apply(String param) { return param.length(); } }).await().result()); Some(6)
  • 34. Futures in Akka 1.1 val upperIt = actorOf(classOf[ToUpperActor]).start val doubleFoo = doubleIt !!! &quot;foo&quot; val upperBar = upperIt !!! &quot;bar&quot; println( (for ( x:String <- doubleFoo; y:String <- upperBar ) yield (x + y)).await.result ) Some(foofooBAR)
  • 35.
  • 36. Anonymous actors val fooActor = Actor.actorOf( new Actor { def receive = { case x => println(&quot;Foo: &quot; + x) } }).start
  • 37. Anonymous actors Unfortunately this does not work: ActorRef act = Actors.actorOf(new UntypedActor() { public void onReceive(Object message) { System.out.println(&quot;Received : &quot; + message); } }).start();
  • 38. Anonymous actors A factory is needed: ActorRef act = actorOf(new UntypedActorFactory() { public UntypedActor create() { return new UntypedActor() { public void onReceive(Object message) { System.out.println(&quot;Received : &quot; + message); } }; } }).start();
  • 39. No built-in pattern matching in Java (Author's idea, not part of Akka) public void onReceive(Object message) { Matchable matchable = new Matchable(message); for (Integer value : matchable.matchesInteger(equalTo(42))) { System.out.println(value + &quot; is the answer !&quot;); } for (Integer value : matchable.matchesInteger()) { System.out.println(value + &quot; is a number, but not the answer.&quot;); } for (Object value : matchable) { System.out.println(value + &quot; is not even close.&quot;); } } - Matchable is an Iterable that can only be iterated once - Idea inspired similar idea in Play! framework - Uses Hamcrest matchers
  • 40. Scala equivalent def receive = { case value:Integer if (value == 42) => println(value + &quot; is the answer !&quot;) case value:Integer => println(value + &quot; is a number, but not the answer.&quot;) case value:Any => println(value + &quot; is not even close.&quot;) }
  • 41. Typed actors public interface Counter { public void increment(); public Integer getValue(); public Future<Integer> getFutureValue(); }
  • 42. Typed actors public class CounterActor extends TypedActor implements Counter { private Integer value = 0; public void increment() { try { Thread.sleep(1000); } catch (InterruptedException ex) { } value++; } public Integer getValue() { return value; } public Future<Integer> getFutureValue() { return future(value); } }
  • 43. Typed actors Counter counter = TypedActor .newInstance(Counter.class, CounterActor.class, 2000); counter.increment(); System.out.println(counter.getValue()); 1 counter.increment(); System.out.println( counter.getFutureValue().get()); 2
  • 44. Server managed remote actors On Remote Server: RemoteServerModule server = remote().start(&quot;localhost&quot;, 2553); server.register(&quot;double-it&quot;, actorOf(DoubleItActor.class)); server.register(&quot;to-string&quot;, actorOf(ToStringActor.class)); On Client: ActorRef doubleIt = remote() .actorFor(&quot;double-it&quot;, &quot;localhost&quot;, 2553); ActorRef toString = remote() .actorFor(&quot;to-string&quot;, &quot;localhost&quot;, 2553); doubleIt.sendOneWay(&quot;meh&quot;, toString); On Remote Server: mehmeh
  • 45. Client managed remote actors ActorRef remoteToString = remote().actorOf( ToStringActor.class, &quot;localhost&quot;, 2553).start(); ActorRef localDoubleIt = Actors.actorOf(DoubleItActor.class).start(); remoteToString.sendOneWay(&quot;foo&quot;); localDoubleIt.sendOneWay(&quot;bar&quot;, remoteToString); On Remote Server: foo barbar Deprecated as of Akka 1.1
  • 46.
  • 48.
  • 49. Priority event based dispatcher val act = actorOf(new Actor { def receive = { case x => println(&quot;Received : &quot; + x) }}) act.dispatcher = new PriorityExecutorBasedEventDrivenDispatcher(&quot;foo&quot;, PriorityGenerator { case _:String => 0 case x:Int => x case _ => 50 }) act.start.dispatcher.suspend(act) act ! 1.0 act ! &quot;foo&quot; (0 to 9).map { x:Int => act ! (x * 10) } act ! 2.0 act ! &quot;bar&quot;
  • 50. Priority event based dispatcher Received : foo Received : 0 Received : bar Received : 10 Received : 20 Received : 30 Received : 40 Received : 1.0 Received : 50 Received : 2.0 Received : 60 Received : 70 Received : 80 Received : 90
  • 51. Work stealing event dispatcher public class FooActor extends UntypedActor { public static MessageDispatcher dispatcher = Dispatchers .newExecutorBasedEventDrivenWorkStealingDispatcher(&quot;foobar&quot;, 5) .build(); private static int currentId = 0; private final int instanceId; private int count = 0; public FooActor() { getContext().setDispatcher(dispatcher); instanceId = currentId++; }
  • 52. Work stealing event dispatcher @Override public void onReceive(Object message) { System.out.printf( &quot;Foo %d processed : %s (count = %d) on Thread : %s&quot;, InstanceId, message.toString(), ++count, Thread.currentThread().getName() ); try { Thread.sleep(instanceId * 50 + 50); } catch (InterruptedException ex) { } }
  • 53. Foo 0 processed : 0 (count = 1) on Thread : akka:event-driven:dispatcher:foobar-1 Foo 1 processed : 1 (count = 1) on Thread : akka:event-driven:dispatcher:foobar-2 Foo 0 processed : 2 (count = 2) on Thread : akka:event-driven:dispatcher:foobar-3 Foo 1 processed : 3 (count = 2) on Thread : akka:event-driven:dispatcher:foobar-4 Foo 0 processed : 4 (count = 3) on Thread : akka:event-driven:dispatcher:foobar-5 Foo 1 processed : 5 (count = 3) on Thread : akka:event-driven:dispatcher:foobar-6 Foo 0 processed : 6 (count = 4) on Thread : akka:event-driven:dispatcher:foobar-7 Foo 0 processed : 7 (count = 5) on Thread : akka:event-driven:dispatcher:foobar-8 Foo 1 processed : 8 (count = 4) on Thread : akka:event-driven:dispatcher:foobar-9 Foo 0 processed : 9 (count = 6) on Thread : akka:event-driven:dispatcher:foobar-10
  • 54. Foo 1 processed : 93 (count = 40) on Thread : akka:event-driven:dispatcher:foobar-15 Foo 0 processed : 94 (count = 55) on Thread : akka:event-driven:dispatcher:foobar-13 Foo 0 processed : 95 (count = 56) on Thread : akka:event-driven:dispatcher:foobar-13 Foo 0 processed : 96 (count = 57) on Thread : akka:event-driven:dispatcher:foobar-16 Foo 1 processed : 97 (count = 41) on Thread : akka:event-driven:dispatcher:foobar-14 Foo 0 processed : 98 (count = 58) on Thread : akka:event-driven:dispatcher:foobar-4 Foo 1 processed : 99 (count = 42) on Thread : akka:event-driven:dispatcher:foobar-4
  • 55.
  • 56.
  • 58. Routing and load balancing InfiniteIterator<ActorRef> iter = new CyclicIterator<ActorRef>(Arrays.asList( actorOf(FooActor.class).start(), actorOf(BarActor.class).start() )); for (Integer value:Arrays.asList(4, 8, 15, 16, 23, 42)) { iter.next().sendOneWay(value); } Bar: 8 Foo: 4 Bar: 16 Foo: 15 Bar: 42 Foo: 23
  • 59. Routing and load balancing ActorRef router = actorOf(new UntypedActorFactory() { public UntypedActor create() { return new UntypedLoadBalancer() { private InfiniteIterator iterator = new CyclicIterator<ActorRef>(Arrays.asList( actorOf(FooActor.class).start(), actorOf(BarActor.class).start())); public InfiniteIterator<ActorRef> seq() { return iterator; } }; }}).start(); for (Integer value : Arrays.asList(4, 8, 15, 16, 23, 42)) { router.sendOneWay(value); }
  • 60. Routing and load balancing class SleepyCounterActor(name:String, sleepyTime:Int) extends Actor { var count = 0 def receive = { case x => { Thread.sleep(sleepyTime) count += 1; printf(&quot;%s received '%s' count = %d&quot;, name, x, count) } }
  • 61. Routing and load balancing val iter = new SmallestMailboxFirstIterator(List( actorOf(new SleepyCounterActor(&quot;Foo&quot;, 1)).start, actorOf(new SleepyCounterActor(&quot;Bar&quot;, 50)).start)) (1 to 15).foreach { x:Int => Thread.sleep(2) iter.next ! x }
  • 62. Routing and load balancing val balancer = loadBalancerActor (new SmallestMailboxFirstIterator(List( actorOf(new SleepyCounterActor(&quot;Foo&quot;, 1)).start, actorOf(new SleepyCounterActor(&quot;Bar&quot;, 50)).start) ) ) (1 to 15).foreach { x:Int => Thread.sleep(2) balancer ! x }
  • 63. Routing and Load Balancing Foo received '3' count = 1 Foo received '4' count = 2 Foo received '6' count = 3 Foo received '8' count = 4 Foo received '9' count = 5 Foo received '10' count = 6 Foo received '11' count = 7 Foo received '12' count = 8 Foo received '13' count = 9 Foo received '14' count = 10 Foo received '15' count = 11 Bar received '1' count = 1 Bar received '2' count = 2 Bar received '5' count = 3 Bar received '7' count = 4
  • 64. Supervision and fault tolerance class DivideInto10Actor extends Actor { def receive = { case x:Int => self.reply_?(10 / x) } override def preStart { print(&quot;DivideInto10Actor.preStart()&quot;) } override def postStop { print(&quot;DivideInto10Actor.postStop()&quot;) } override def preRestart(reason: Throwable) { printf(&quot;DivideInto10Actor.preRestart(%s)&quot;, reason.getMessage) } override def postRestart(reason: Throwable) { printf(&quot;DivideInto10Actor.postRestart(%s)&quot;, reason.getMessage) } }
  • 65. Supervision and fault tolerance val supervisedActors = Array( actorOf(classOf[DivideInto10Actor]), actorOf(classOf[DivideInto10Actor]) ) val supervisor = Supervisor( SupervisorConfig( OneForOneStrategy(List(classOf[Exception]), 3, 1000), List( Supervise(supervisedActors(0), Permanent), Supervise(supervisedActors(1), Temporary) ))) DivideInto10Actor.preStart() DivideInto10Actor.preStart()
  • 66. Supervision and fault tolerance supervisedActors(0) ! 0 // Permanent DivideInto10Actor.postStop() java.lang.ArithmeticException: / by zero ... DivideInto10Actor.preRestart(/ by zero) DivideInto10Actor.preStart() DivideInto10Actor.postRestart(/ by zero) supervisedActors(1) ! 0 // Temporary DivideInto10Actor.postStop() java.lang.ArithmeticException: / by zero ... DivideInto10Actor.preRestart(/ by zero) DivideInto10Actor.preStart() DivideInto10Actor.postRestart(/ by zero)
  • 67. Supervision and fault tolerance With OneForOneStrategy: SupervisedActors(0) ! 0 // Permanent DivideInto10Actor.preRestart(/ by zero) java.lang.ArithmeticException: / by zero ... DivideInto10Actor.preStart() DivideInto10Actor.postRestart(/ by zero) SupervisedActors(1) ! 0 // Temporary DivideInto10Actor.postStop() java.lang.ArithmeticException: / by zero
  • 68. Supervision and fault tolerance val supervisor = Supervisor( SupervisorConfig( OneForOneStrategy(List(classOf[Exception]), 3, 1000), Nil )) supervisedActors(0).setLifeCycle(Permanent) supervisedActors(0).start supervisor.link(supervisedActors(0)) supervisedActors(1).setLifeCycle(Temporary) supervisedActors(1).start supervisor.link(supervisedActors(1))
  • 69. Supervision and fault tolerance val supervisor = Supervisor( SupervisorConfig( OneForOneStrategy(List(classOf[Exception]), 3, 1000), Nil )) supervisedActors(0).setLifeCycle(Permanent) supervisor.startLink(supervisedActors(0)) supervisedActors(1).setLifeCycle(Temporary) supervisor.startLink(supervisedActors(1))
  • 70. Supervision and fault tolerance class CustomSupervisor extends Actor { self.faultHandler = OneForOneStrategy( List(classOf[Throwable]), 5, 5000) def receive = { case x => println(&quot;CustomSupervisor received : &quot; + x) } } val supervisor = actorOf(classOf[CustomSupervisor]).start supervisedActors(0).setLifeCycle(Permanent) supervisor.startLink(supervisedActors(0)) supervisedActors(1).setLifeCycle(Temporary) supervisor.startLink(supervisedActors(1))
  • 71. Scheduler Scheduler.schedule( receiverActor, messageToBeSent, initialDelayBeforeSending, delayBetweenMessages, timeUnit) Scheduler.scheduleOne( receiverActor, messageToBeSent, delayUntilSend, timeUnit)
  • 72. Scheduler Scheduler.schedule( toString, &quot;ping&quot;, 0, 5, TimeUnit.SECONDS ); Scheduler.scheduleOnce( toString, &quot;pong&quot;, 15, TimeUnit.SECONDS );
  • 73. Declarative configuration akka.conf: akka { version = &quot;1.1&quot; enabled-modules = [&quot;camel&quot;, &quot;http&quot;] time-unit = &quot;seconds&quot; event-handlers = [&quot;akka.event.EventHandler$DefaultListener&quot;] event-handler-level = &quot;INFO&quot; ... actor { timeout = 5 serialize-messages = off throughput = 5 ...
  • 74. Declarative configuration default-dispatcher { type = &quot;GlobalExecutorBasedEventDriven&quot; keep-alive-time = 60 core-pool-size-factor = 1.0 max-pool-size-factor = 4.0 mailbox-capacity = -1 rejection-policy = &quot;caller-runs&quot; throughput = 5 ...
  • 75. Data Flow concurrency val x, y, z = Promise[Int] flow { z << x() + y() println(&quot;z = &quot; + z()) } flow { x << 40 } flow { y << 2 } } z = 42
  • 76. Back to (the) Future val future = Future { Thread.sleep(1000) 42 } val doubleItActor = actorOf(new Actor { def receive = { case x:Int => Thread.sleep(1000); self.reply(x * 2) case _ => self.reply(0) } } ).start val actorReply:Future[Int] = doubleItActor !!! 73 val promise = Promise[Int]
  • 77. Back to (the) Future flow { promise << 23 } val totalFuture = for { x <- future y <- actorReply c <- promise } yield ( x + y + c ) println(totalFuture.get) 211
  • 78. Back to (the) Future flow { println (future() + promise() + actorReply()) } 211
  • 79. Back to (the) Future val resultList = Future. sequence ( List(future, actorReply, promise)).get println (resultList) List(42, 146, 23) println (resultList.reduce(_ + _)) 211
  • 80.  
  • 81. Map-Reduce (like) with Akka (finding anagrams)
  • 82. Stateful behaviors val doubleIt = actorOf(classOf[DoubleItActor]) .start println(doubleIt !! &quot;foo&quot;) Some(foofoo) doubleIt ! HotSwap ( self => { case message => self.reply( message.toString + message.toString + &quot; hotswapped&quot;) }) println(doubleIt !! &quot;bar&quot;) Some(barbar hotswapped) doubleIt ! RevertHotSwap println(doubleIt !! &quot;meh&quot;) Some(mehmeh)
  • 83. Stateful behaviors class FooActor extends UntypedActor { public void onReceive(Object message) { if (&quot;foo&quot;.equals(message)) { become(BAR_BEHAVIOR); } else { getContext().replySafe(&quot;foo&quot;); } }
  • 84. Stateful behaviors private final Procedure<Object> BAR_BEHAVIOR = new Procedure<Object>() { @Override public void apply(Object param) { getContext().replySafe(&quot;bar&quot;); unbecome(); } };
  • 85. Stateful behaviors System.out.println(actorRef.sendRequestReply(&quot;bar&quot;)); actorRef.sendOneWay(&quot;foo&quot;); System.out.println(actorRef.sendRequestReply(&quot;bar&quot;)); System.out.println(actorRef.sendRequestReply(&quot;bar&quot;)); foo bar foo
  • 86. Finite state machine in an Actor (vending machine)
  • 87.
  • 88. A form on optimistic locking for memory
  • 89.
  • 90. Refs val ref1 = new Ref(4) val ref2 = new Ref(4) println(&quot;ref1 = &quot; + ref1.get) println(&quot;ref2 = &quot; + ref2.get) try { atomic { ref1.swap(12) ref2.alter(_ * 2) ref1.alter(_ / 0) } } catch { case ex:Exception => println(ex.getMessage) } println(&quot;ref1 = &quot; + ref1.get) println(&quot;ref2 = &quot; + ref2.get) ref1 = 4 ref2 = 4 / by zero ref1 = 4 ref2 = 4
  • 91. Refs val ref1 = new Ref(4) val ref2 = new Ref(4) println(&quot;ref1 = &quot; + ref1.get) println(&quot;ref2 = &quot; + ref2.get) try { ref1.swap(12) ref2.alter(_ * 2) ref1.alter(_ / 0) } catch { case ex:Exception => println(ex.getMessage) } println(&quot;ref1 = &quot; + ref1.get) println(&quot;ref2 = &quot; + ref2.get) ref1 = 4 ref2 = 4 / by zero ref1 = 12 ref2 = 8
  • 92. Refs final Ref<Integer> ref1 = new Ref(4); final Ref<Integer> ref2 = new Ref(4); new Atomic<Integer>() { public Integer atomically() { ref1.set(8); ref2.set(12); return (Integer) ref1.get() + (Integer) ref2.get(); } }.execute());
  • 93.
  • 94.
  • 95. Transactional datastructues val tranMap = TransactionalMap[String, Int](&quot;Foo&quot; -> 23) val tranVector = TransactionalVector(2.0, 4.0, 6.0) try { atomic { tranMap += (&quot;Bar&quot; -> 42) tranVector.add(8.0) println(tranMap) println(tranVector) 1 / 0 } } catch { case ex:Any => println(ex) } atomic { println(tranMap); println(tranVector) } Map(Bar -> 42, Foo -> 23) TransactionalVector(2.0, 4.0, 6.0, 8.0) java.lang.ArithmeticException: / by zero Map(Foo -> 23) TransactionalVector(2.0, 4.0, 6.0)
  • 97. Philosopher 3 wants to ponder Philosopher 4 sees forks available Philosopher 1 sees forks available Philosopher 4 eats Philosopher 1 eats Philosopher 2 sees forks available Philosopher 2 can't get forks Philosopher 2 can't get forks Philosopher 5 can't get forks
  • 98. Agents val agent = new Agent(5) val times2 = { x:Int => x * 2 } agent.send(times2) agent.send(_ - 1) agent.send(_ * 3) println(agent.get) 5 Thread.sleep(1000) println(agent.get) 27
  • 99. Agents Agent<Integer> agent = new Agent<Integer>(5); AbstractFunction1<Integer, Integer> times2 = new AbstractFunction1<Integer, Integer>() { public final Integer apply(Integer x) { return x * 2; } }; agent.send(times2); agent.send(times2); 5 System.out.println(agent.get()); try { Thread.sleep(1000); } catch (InterruptedException iex) { } System.out.println(agent.get()); 20
  • 100. Coordinated transactions class CoordinatedAccountActor extends Actor { private val balance:Ref[Int] = Ref(0) def doReceive:Receive = { case Withdraw(x) if x > balance.get => throw new Exception(&quot;Overdrawn&quot;) case Withdraw(x) if x > 0 => balance.alter(_ - x) case Deposit(x) if x > 0 => balance.alter(_ + x) case PrintBalance => println(&quot;Balance = &quot; + balance.get) } def receive = { case coordinated @ Coordinated(action) => coordinated atomic { doReceive(action) } case other:Any => doReceive(other) } }
  • 101. Coordinated Transactions account1 ! Deposit(100) account2 ! Deposit(50) val coordinated = Coordinated() try { coordinated atomic { account1 ! coordinated.coordinate(Deposit(75)) account2 ! coordinated.coordinate(Withdraw(75)) } } catch { case ex:Exception => println(ex.getMessage) } org.multiverse.templates.InvisibleCheckedException: java.lang.Exception: Overdrawn account1 ! PrintBalance Balance = 100 account2 ! PrintBalance Balance = 50
  • 102. Transactors class AccountTransactor extends Transactor { private val balance:Ref[Int] = Ref(0) override def atomically = { case Withdraw(x) if x > balance.get => throw new Exception(&quot;Overdrawn&quot;) case Withdraw(x) if x > 0 => balance.alter(_ - x) case Deposit(x) if x > 0 => balance.alter(_ + x) case PrintBalance => println(&quot;Balance = &quot; + balance.get) } }
  • 103. Coordinated typed actors public interface BankAccount { @Coordinated public void withdraw(int amount); @Coordinated public void deposit(int amount); public int getBalance(); }
  • 104. Coordinated typed actors public class BankAccountTypedActor extends TypedActor implements BankAccount { private Ref<Integer> balance = new Ref<Integer>(0); public void withdraw(int amount) { if (amount > 0) { if (amount > balance.get()) { throw new RuntimeException(&quot;Overdrawn&quot;); } else { balance.set(balance.get() - amount); } } } public void deposit(int amount) { if (amount > 0) { balance.set(balance.get() + amount); } } public int getBalance() { return balance.get(); } }
  • 105. Coordinated typed actors public static void transferUnsafe ( BankAccount fromAccount, BankAccount toAccount, int amount) { toAccount.deposit(amount); fromAccount.withdraw(amount); } public static void transferSafe ( final BankAccount fromAccount, final BankAccount toAccount, final int amount) { Coordination.coordinate(true, new Atomically() { public void atomically() { toAccount.deposit(amount); fromAccount.withdraw(amount); } }); }
  • 106. Coordinated typed actors BankAccount account1 = (BankAccount) TypedActor .newInstance(BankAccount.class, BankAccountTypedActor.class, 1000); BankAccount account2 = (BankAccount) TypedActor .newInstance(BankAccount.class, BankAccountTypedActor.class, 1000); account1.deposit(100); account2.deposit(50); try { transferSafe (account1, account2, 150); } catch (Exception ex) { System.err.println(ex.getMessage()); } System.out.println(account1.getBalance()); 100 System.out.println(account2.getBalance()); 50 java.lang.RuntimeException: Overdrawn
  • 107. Coordinated typed actors BankAccount account1 = (BankAccount) TypedActor .newInstance(BankAccount.class, BankAccountTypedActor.class, 1000); BankAccount account2 = (BankAccount) TypedActor .newInstance(BankAccount.class, BankAccountTypedActor.class, 1000); account1.deposit(100); account2.deposit(50); try { transferUnsafe(account1, account2, 150); } catch (Exception ex) { System.err.println(ex.getMessage()); } System.out.println(account1.getBalance()); 100 System.out.println(account2.getBalance()); 200 java.lang.RuntimeException: Overdrawn
  • 108. Integration with Spring <?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?> <beans xmlns=&quot;http://www.springframework.org/schema/beans&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xmlns:akka=&quot;http://akka.io/schema/akka&quot; xsi:schemaLocation=&quot; http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://akka.io/schema/akka http://akka.io/akka-1.1.xsd&quot;> <akka:untyped-actor id=&quot;toStringActor&quot; implementation=&quot;tfd.akkatest.java.ToStringActor&quot; scope=&quot;singleton&quot; autostart=&quot;true&quot;/> </beans>
  • 109.
  • 114.
  • 115.
  • 116.
  • 117. Guice
  • 119.
  • 120.
  • 121.
  • 123. It's Actors All The Way Down ( http://www.dalnefre.com/wp/ )
  • 124. Pure Danger Tech - Actor Concurrency
  • 126. Thank You ! Questions

Hinweis der Redaktion

  1. The Scala ! syntax got confused with sending a tuple
  2. This syntax is also need for any Actor with a non-default Constructor
  3. This syntax is also need for any Actor with a non-default Constructor
  4. This syntax is also need for any Actor with a non-default Constructor