早速ですが、
abstract class ActorRef { def ! (msg: Any)(implicit sender: ActorRef = Actor.noSender): Unit def tell(msg: Any, sender: ActorRef) = this.!(msg)(sender) }
むむ
ここの解釈が、どうも混乱する。sender は送り主なのに tellでメッセージを送られているように見えるし。。
akkaのソースをみることにする
まずはgetting startedからHelloWorldサンプルをダンロードし
中身をみるところから。動画のないようはだいぶ割愛されたスニペットなので。
重要なことの切り出し
① アクターは、メッセージを必ず一個ずつ処理するので、スレッド同士の競合はない。
Note how this Actor manages the counter by changing the behavior for each
Greeted
reply rather than using any variables. No concurrency guards such assynchronized
orAtomicInteger
are needed since an actor instance processes one message at a time.https://developer.lightbend.com/guides/akka-quickstart-scala/define-actors.html
② アクターはspawnでしか生成されずに、アクター自身ではなく、その参照が返される。参照という間接性が、分散システムにおいては大いに功を奏す。
The power of location transparency
In Akka you can’t create an instance of an Actor using the
new
keyword. Instead, you create Actor instances using a factoryspawn
methods. Spawn does not return an actor instance, but a reference,akka.actor.typed.ActorRef
, that points to the actor instance. This level of indirection adds a lot of power and flexibility in a distributed system. https://developer.lightbend.com/guides/akka-quickstart-scala/create-actors.html
つまりはActorRefというのが、同一マシンの1プロセスだろうが、リモートノードだろうが抽象化してくている
ということが嬉しいのです
また必要によってはtopology(どうのようにActorが配置されているか)を動的に変更したり、できるようです。そがゆえに、だめなactorはクラッシュさせても、自動的に回復するような、そんなこともできるそうです。
If needed, the runtime can optimize the system by changing an Actor’s location or the entire application topology while it is running. This enables the “let it crash” model of failure management in which the system can heal itself by crashing faulty Actors and restarting healthy ones.
いつもおもっていたActorSystemとは何ぞや?
Guardian actorとっていますが、用はほんとに最初のActorを生成するためのアクターである程度の初期化とか終了処理とかを担っているのでしょう。
The Akka ActorSystem
An
ActorSystem
is the intial entry point into Akka, usually only one is created per application. AnActorSystem
has a name and a guardian actor. The bootstrap of your application is typically done within the guardian actor.The Hello World guardian actor is
GreeterMain
.
で基本Actorはspawnで生まれるんだって。
次に
③ アクターはメッセージを受け取るまでは何もしない。Actorはイベント駆動です、というかメッセージ駆動です。
Actors are reactive and message driven. An Actor doesn’t do anything until it receives a message
④ メッセージはmailboxに投げ込まれて、終わりなので非同期である。とどのつまりmailboxとカッコよく読んでいるがmessage queueである。
the sender puts the message in the recipient’s mailbox and is free to do other work. The Actor’s mailbox is essentially a message queue with ordering semantics.
ここでActorとスレッドはどう違うのか?という疑問が湧いた。この疑問はactorは処理をしていない間リソースを食うのか?いいえ、それはないです、という内容を読んでいる時に浮かんだ
素晴らしい回答をくれているstackoverflowを見つけたので共有したい
Actorは、ひとつの非同期コミュニケーションの抽象化した概念で、スレッドで実現しようが、されまいがあまり関係ない。
wow
メッセージを受け取り、それに対する処理をするということ。メッセージは1Actorにつき1メッセージづつ処理されること。で、内部の処理としては先程mailboxはmessage queueだよ、と出てきたように、Actorを見事に図示してくれている。ということで単に、queueと、メッセージ受けたと時の処理が書かれている、だけのentity, objectである。
https://stackoverflow.com/questions/47248820/difference-in-definition-of-actors-vs-threads
そして、メッセージを処理するときに同一Threadで行うとか、thread poolから取ってくるとか
が実行されるわけです。こういうイメージ一枚あると、全然理解が違ってきます。
https://stackoverflow.com/questions/47248820/difference-in-definition-of-actors-vs-threads
これ!の読み方はbangとかtellとか、というらしんですが
greeterMain ! SayHello("Charles")
は、SayHelloというメッセージをgreeterMainに送る
というのが、全て理解した人の読み方なのだけど、オブジェクト指向って基本左から右へ
英語の文法のようい読めるものだから、それに反していてい、とてもとても読みづらい。
なので
greeterMainがSayHelloをqueued-upする
greeterMain ! SayHello("Charles")
と読みます。
私はqueued-upとよんだほうがideomaticだと思いますし、なれるまで
そうしたい。
先ほども言ったようにアクタシステムっていうのはガーディアンアクターであり、アプリケーションを bootstrap するためのアクターである。典型的にこのアクターは`Behaviors.setup`を呼び出すことで設定されます
以上です