zakgof / actr

Simple, fast and typesafe Java actor model implementation
Apache License 2.0
119 stars 20 forks source link
actor-model actors akka concurrency java

actr

Travis CI Maven Central

Simple actor model implementation for Java

Actor code is guaranteed to be executed in thread-safe context:

Actr's API philosophy is discussed here: https://medium.com/@zakgof/type-safe-actor-model-for-java-7133857a9f72

Schedulers

Schedulers are available to be configured on per-actor or per-actor-system basis.

It's easy to introduce your own fine-tuned scheduler by just implementing IActorScheduler.

Comparison to akka

Akka will require more boilerplate code. Code with Actr will be more concise.

Akka Actr
Type safety No. Sending any message to any actor won't reveal any problems at compile time Type safe
Actor implementation class Must extend AbstractActor No constraints
Message Must create a class for every message type Message type is represented by a method
Message type dispatching Must implement dispatching Message type = method, no need for implementing dispatching
Passing multiple params Must pack into a single message class Message type = method, so supported

Compare the same example implemented with akka and actr. (Note the difference in Printer implementation. With akka, the implementation is 41 lines long with only 1 line of business code (line 34))

Performance

Actr outperforms Akka on common actor operations. A complete opensource benchmark is available here: https://github.com/zakgof/akka-actr-benchmark

Setup

Actr is on Maven Central

Gradle

implementation 'com.github.zakgof:actr:0.4.2'

Maven

<dependency>
  <groupId>com.github.zakgof</groupId>
  <artifactId>actr</artifactId>
  <version>0.4.2/version>
</dependency>

Usage

Having a POJO class

private static class Printer {

    public void print(String s) {
        // This is called in Printer's thread
        System.err.println("[Printer] " + s);
    }
    public String getName() {
        // This is called in Printer's thread
        return "Printer-1";
    }
}

Create an actor

final IActorRef<Printer> printerActor = Actr.newActorSystem("default").actorOf(Printer::new);

Call Printer from another actor


    public void run() {
        // Tell: send text to print
        printerActor.tell(printer -> printer.print("Hello !"));

        // Ask: retrieve printer name. Printer#getName runs in Printer's thread, #printerNameReply runs in Caller's thread
        printerActor.ask(Printer::getName, this::printerNameReceived);
    }

    private void printerNameReceived(String printerName) {
       // Do smth with Printer's name
       // This is called in Caller's thread
    }

More examples

https://github.com/zakgof/actr/tree/master/src/example/java/com/zakgof/actr/example