LoginSignup
27
28

More than 5 years have passed since last update.

JavaからAkkaを使う

Posted at

みなさん、Akka使ってますか。AkkaはActorモデルを使った並行処理を簡単に書くためのScalaのライブラリです。
でも私はScalaがあまり好きではないので、Javaから使っています。
AkkaはJava用のインターフェイスとドキュメントもしっかり揃っており、使い勝手はかなり異なりますが、Javaでもほぼ全ての機能を使うことができます。

準備

AkkaのドキュメントGetting startedに則って、SBTを使って必要なライブラリを集めます。SBTのインストール方法や使い方はここでは説明しません。
(http://doc.akka.io/docs/akka/snapshot/intro/getting-started.html)

build.sbt
name := "akka"

version := "1.0"

scalaVersion := "2.11.5"

resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/"

libraryDependencies ++=
  Seq("com.typesafe.akka" % "akka-actor_2.11" % "2.3.9")

Actorの実装

EchoActor.java
public class EchoActor extends UntypedActor {
    public EchoActor() {
        System.out.println("constructor");
    }

    @Override
    public void onReceive(Object message) throws Exception {
        if (message instanceof String) {
            System.out.println("Got message. " + message);
            getSender().tell(message, getSender());
        } else {
            System.out.println("Got unknown type message.");
            unhandled(message);
        }
    }
}

まずActorを作ります。akka.actorパッケージのUntypedActorというクラスを継承して、onReceiveというメソッドを実装します。
"Untyped"はOnReceiveメソッドで受け取れるメッセージの型はなんでも良い(Object)であることを示しています。
onReceiveメソッドは、メッセージ(Object)を別のActor等から受け取った時に呼ばれるコールバックメソッドです。
メッセージを受け取っていない時は、特に何もしません。

onReceiveはどんな型のメッセージでも受け取れてしまうため、メッセージの型や中身を見て処理を分岐してあげる必要があります。
Javaにはパターンマッチがないため、このあたりの処理がやや煩雑になりがちです・・・。

Main.java
public class Main {

    public static void main(String[] args) {
        ActorSystem system = ActorSystem.create("EchoSystem");
        ActorRef echoActorRef = system.actorOf(Props.create(EchoActor.class), "EchoActor");
        echoActorRef.tell("Hello world", ActorRef.noSender());
        system.stop(echoActorRef);
        system.shutdown();
    }
}

次に、EchoActorの実体を生成して、Actorにメッセージを送る部分を実装します。今回は安易にmainに実装しました。

ActorSystemは、Actorを管理するためのオブジェクトです。どんなActorもどこかのActorSystemに所属することになります。
ActorSystemは、到来したメッセージを振り分けたり、Actorを動かすためのスレッドプールの管理等をやっているようです。

ActorSystemを生成したあとは、ActorSystemのメソッドであるactorOfを経由してEchoActorの実体を生成し、その参照であるActorRefを得ます。
ActorRef自身はActorの実体を持っておらず、Actorへのアドレスだけを持っています。なぜ参照なのかは色々と事情があります。(今回は説明しません)

3行目で、tellメソッドを使ってEchoActorへメッセージを送信します。tellメソッドは非同期に実行されます。今回はメッセージを送った結果を確認する方法を実装していないので、EchoActorに何が起こったかをmainメソッドの中では知ることはできません。

4,5行目は、Actorの停止とActorSystemの停止処理です。
stopメソッドはActorがメッセージを処理している最中の場合には、それが終わるまで待ってから停止を試みます。(ちゃんとした理由がありますが、今回は説明しません)
また、ActorSystemの停止をするshutdownメソッドはSystemに所属している全てのActorがメッセージを処理し終わるまで待ってから停止を試みます。

27
28
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
28