Akka entry-become and unbecome, akkaunbecome
Akka supports real-time replacement of the role message loop (such as its implementation) at runtime: Call the getContext. become method in the role. Hot replacement code is stored in a stack and can be pushed (replacing or adding at the top) and popped.
A particularly good example of become is to use it to implement a finite state machine.
The Become/Unbecome feature can also be used to conveniently implement status conversion machines.
1. Dynamic Replacement Method
import akka.actor.ActorRef;import akka.actor.ActorSystem;import akka.actor.Props;import akka.actor.UntypedActor;import akka.event.Logging;import akka.event.LoggingAdapter;import akka.japi.Procedure;public class UntypedActorSwapper { public static class Swap { public static Swap SWAP = new Swap(); private Swap() {} } public static class Swapper extends UntypedActor { LoggingAdapter log = Logging.getLogger(getContext().system(), this ); public void onReceive(Object message ) { if ( message == Swap. SWAP ) { log.info( "Hi" ); getContext().become( new Procedure<Object>() { public void apply(Object arg0) throws Exception { log.info( "Ho" ); getContext().unbecome(); // resets the latest 'become' } }, false ); // this signals stacking of the new behavior } else { unhandled( message); } } } public static void main(String... args) { ActorSystem system = ActorSystem. create( "MySystem"); ActorRef swap = system .actorOf(Props.create(Swapper. class )); swap.tell(Swap. SWAP , ActorRef.noSender()); // logs Hi swap.tell(Swap. SWAP , ActorRef.noSender()); // logs Ho swap.tell(Swap. SWAP , ActorRef.noSender()); // logs Hi swap.tell(Swap. SWAP , ActorRef.noSender()); // logs Ho swap.tell(Swap. SWAP , ActorRef.noSender()); // logs Hi swap.tell(Swap. SWAP , ActorRef.noSender()); // logs Ho }}
Output result:
[INFO] [05/18/2015 22:49:10.122] [MySystem-akka.actor.default-dispatcher-2] [akka://MySystem/user/$a] Hi[INFO] [05/18/2015 22:49:10.123] [MySystem-akka.actor.default-dispatcher-2] [akka://MySystem/user/$a] Ho[INFO] [05/18/2015 22:49:10.123] [MySystem-akka.actor.default-dispatcher-2] [akka://MySystem/user/$a] Hi[INFO] [05/18/2015 22:49:10.123] [MySystem-akka.actor.default-dispatcher-2] [akka://MySystem/user/$a] Ho[INFO] [05/18/2015 22:49:10.123] [MySystem-akka.actor.default-dispatcher-2] [akka://MySystem/user/$a] Hi[INFO] [05/18/2015 22:49:10.123] [MySystem-akka.actor.default-dispatcher-2] [akka://MySystem/user/$a] Ho
2. Achieve A Classic Philosophical View of dining issues
The dining question of philosophers can be expressed in this way. Suppose five philosophers sat around a circular dining table and did one of the following two things: eating or thinking. When they eat, they stop thinking, and when they think about it, they also stop eating. There is a bowl of pasta in the middle of the dining table, with a dining cross between every two philosophers. It is difficult to use a cross to eat pasta, so it is assumed that philosophers must use two forks to eat. They can only use the two forks on their left and right sides. Philosophers sometimes describe dining problems with rice and chopsticks instead of pasta and forks, because it is obvious that two chopsticks are required to eat rice.
In the following programs, hackers play philosophers and chopsticks play the forks. Eat chopsticks !! Wild programmer!
Import static com. center. akka. become. messages. eat; import static com. center. akka. become. messages. think; import static java. util. concurrent. timeUnit. MILLISECONDS; import static java. util. concurrent. timeUnit. SECONDS; import java. util. arrayList; import java. util. arrays; import java. util. list; import scala. partialFunction; import scala. concurrent. duration. duration; import scala. concurrent. duration. finiteDur Ation; import scala. runtime. boxedUnit; import akka. actor. extends actactor; import akka. actor. actorRef; import akka. actor. actorSystem; import akka. actor. props; import akka. japi. pf. FI. typedPredicate; import akka. japi. pf. FI. unitApply; import akka. japi. pf. receiveBuilder; import com. center. akka. become. messages. busy; import com. center. akka. become. messages. put; import com. center. akka. become. messages. take; import com. ce Nter. akka. become. messages. taken; public class DiningHakkersOnBecome {/** chopsticks are an Actor, it can be obtained or put down */public static class Chopstick extends actactor {// when a pair of chopsticks is taken by a hacker, the attacker is denied to take the other one, and the hacker with chopsticks needs to put back the chopsticks PartialFunction <Object, BoxedUnit> takenBy (final ActorRef hakker) {return ReceiveBuilder. match (Take. class, new UnitApply <Take> () {public void apply (Take t) throws Exception {t. hakker. Tell (new Busy (self (), self ());}}). match (Put. class, new TypedPredicate <Put> () {public boolean defined (Put p) {return p. hakker = hakker; }}, new UnitApply <Put> () {public void apply (Put p) throws Exception {context (). become (available );}}). build () ;}// chopsticks available status PartialFunction <Object, BoxedUnit> available = ReceiveBuilder. match (Take. class, new UnitApply <Take> () {public void apply (T Ake t) throws Exception {context (). become (takenBy (t. hakker); t. hakker. tell (new Taken (self (), self ());}}). build (); // set the initial state to public Chopstick () {receive (available);} public static class Hakker extends actactor {private String name; private ActorRef left; private ActorRef right; public Hakker (final String name, ActorRef left, ActorRef right) {this. name = name; this. left = Left; this. right = right; // set the default value. First, consider receive (ReceiveBuilder. matchEquals (Think, new UnitApply <Object> () {public void apply (Object I) throws Exception {System. out. println (String. format ("% s starts to think", name); startThinking (Duration. create (5, SECONDS ));}}). build ();} public Hakker () {receive (ReceiveBuilder. matchEquals (Think, new UnitApply <Object> () {public void apply (Object I) throws Exception {System. out. println (String. format ("% s starts to think", name); startThinking (Duration. create (5, SECONDS ));}}). build ();} // eating behavior: When a hacker eats, he decides to start thinking and put down the chopsticks in his hands. PartialFunction <Object, BoxedUnit> eating = ReceiveBuilder. matchEquals (Think, new UnitApply <Object> () {public void apply (Object I) throws Exception {left. tell (new Put (self (), self (); right. tell (new Put (self (), self (); System. out. println (String. format ("% s puts down his chopsticks and starts to think", name); startThinking (Duration. create (5, SECONDS ));}}). build (); // wait for another choppy action: When a hacker waits for another When a chopstick exists, he can get another one to eat. If another Chopstick is occupied, he will give up his existing chopsticks and continue to think about how to get them for dinner !! PartialFunction <Object, BoxedUnit> waitingFor (final ActorRef chopstickToWaitFor, final ActorRef otherChopstick) {return ReceiveBuilder. match (Taken. class, new TypedPredicate <Taken> () {public boolean defined (Taken t) {return t. chopstick = chopstickToWaitFor; }}, new UnitApply <Taken> () {public void apply (Taken I) throws Exception {System. out. println (String. format ("% s has picked up % s And % s and starts to eat ", name, left. path (). name (), right. path (). name (); context (). become (eating); context (). system (). scheduler (). scheduleOnce (Duration. create (5, SECONDS), self (), Think, context (). system (). dispatcher (), self ());}}). match (Busy. class, new UnitApply <Busy> () {public void apply (Busy B) throws Exception {otherChopstick. tell (new Put (self (), self (); startThinking (Duration. Create (10, MILLISECONDS ));}}). build ();} // discard chopsticks: If the chopsticks are not caught, continue to think about PartialFunction <Object, BoxedUnit> deniedac1_stick = ReceiveBuilder. match (Taken. class, new UnitApply <Taken> () {public void apply (Taken t) throws Exception {t. chopstick. tell (new Put (self (), self (); startThinking (Duration. create (10, MILLISECONDS ));}}). match (Busy. class, new UnitApply <Busy> () {public void apply (Busy B) Throws Exception {startThinking (Duration. create (10, MILLISECONDS ));}}). build (); // ELE. Me behavior: When a hacker is hungry, he will try to pick up chopsticks to eat. When he gets a chopstick, he will wait to get another chopstick; if he fails to get a chopstick, he will wait for the response from the next chopstick attempt. PartialFunction <Object, BoxedUnit> hungry = ReceiveBuilder. match (Taken. class, new TypedPredicate <Taken> () {public boolean defined (Taken t) {return t. chopstick = left ;}}, new UnitApply <Taken> () {public void apply (Taken t) throws Exception {context (). become (waitingFor (right, left ));}}). match (Taken. class, new TypedPredicate <Taken> () {public boolean defined (Taken t) {return t. chopstick = right ;}, new UnitApply <Taken> () {public void apply (Taken t) throws Exception {context (). become (waitingFor (left, right ));}}). match (Busy. class, new UnitApply <Busy> () {public void apply (Busy B) throws Exception {context (). become (deniedAChopstick );}}). build (); // thinking behavior: When hackers think about it, they will be hungry. Then they will pick up chopsticks to eat PartialFunction <Object, BoxedUnit> thinking = ReceiveBuilder. matchEquals (Eat, new UnitApply <Object> () {public void apply (Object I) throws Exception {context (). become (hungry); left. tell (new Take (self (), self (); right. tell (new Take (self (), self ());}}). build (); private void startThinking (FiniteDuration duration) {// set the current behavior to think about context (). become (thinking); // go to the context () after a scheduled period of time (). system (). scheduler (). scheduleOnce (duration, self (), Eat, context (). system (). dispatcher (), self () ;}} public static void main (String [] args) {ActorSystem = ActorSystem. create (); // create 5 pairs of chopsticks ActorRef [] chopsticks = new ActorRef [5]; for (int I = 0; I <5; I ++) chopsticks [I] = system. actorOf (Props. create (Chopstick. class), "Chopstick" + I); // create five hackers and assign the chopsticks List <String> names = Arrays. asList ("Ghosh", "Boner", "Klang", "kraser", "Manie"); List <ActorRef> hakkers = new ArrayList <ActorRef> (); int I = 0; for (String name: names) {hakkers. add (system. actorOf (Props. create (Hakker. class, name, chopsticks [I], chopsticks [(I + 1) % 5]); I ++ ;}// start, the initial state of the hacker is to think about for (ActorRef ar: hakkers) {ar. tell (Think, ActorRef. noSender ());}}}
Output result:
Ghosh starts to thinkManie starts to thinkKrasser starts to thinkBoner starts to thinkKlang starts to thinkKlang has picked up Chopstick2 and Chopstick3 and starts to eatManie has picked up Chopstick4 and Chopstick0 and starts to eatKlang puts down his chopsticks and starts to thinkBoner has picked up Chopstick1 and Chopstick2 and starts to eatManie puts down his chopsticks and starts to thinkKrasser has picked up Chopstick3 and Chopstick4 and starts to eatBoner puts down his chopsticks and starts to thinkGhosh has picked up Chopstick0 and Chopstick1 and starts to eatKrasser puts down his chopsticks and starts to thinkKlang has picked up Chopstick2 and Chopstick3 and starts to eat......