Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Write You An Actor (System) For Great Good!

Write You An Actor (System) For Great Good!

Edoardo Vacchi

March 27, 2023
Tweet

More Decks by Edoardo Vacchi

Other Decks in Programming

Transcript

  1. Write You an
    Actor (System) for
    Great Good!
    (with JBang, JDK 19, records, pattern
    matching and virtual threads!)

    View full-size slide

  2. Andrea
    Peruffo
    @and_prf
    Edoardo
    Vacchi
    @evacchi

    View full-size slide

  3. This Is Not A Talk
    About Actor
    Systems

    View full-size slide

  4. This Is Not A Talk
    About Actor
    Systems

    View full-size slide

  5. This Is Not Only A Talk
    About Actor
    Systems

    View full-size slide

  6. evacchi.github.io

    View full-size slide

  7. @evacchi
    About Me
    Edoardo Vacchi @evacchi
    ● PL/DSL Research @ UniMi
    ● R&D @ UniCredit Bank
    ● Drools, Kogito @ Red Hat

    View full-size slide

  8. gist.github.com/viktorklang/2362563

    View full-size slide

  9. gist.github.com/viktorklang/2362563

    View full-size slide

  10. Has Java reached
    feature parity with
    10-years ago Scala?

    View full-size slide

  11. Has Java reached
    feature parity with
    10-years ago Scala?

    View full-size slide

  12. Has Java reached
    feature parity with
    10-years ago Scala?

    View full-size slide

  13. Has Java reached
    feature parity with
    10-years ago Scala?

    View full-size slide

  14. package io.github.evacchi;
    import java.util.concurrent.*;
    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.function.Function;
    import static java.lang.System.out;
    public interface Actor {
    interface Behavior extends Function {}
    interface Effect extends Function {}
    interface Address { Address tell(Object msg); }
    static Effect Become(Behavior like) { return old -> like; }
    static Effect Stay = old -> old;
    static Effect Die = Become(msg -> { out.println("Dropping msg [" + msg + "] due to severe case of death."); return Stay; });
    record System(ExecutorService executorService) {
    public Address actorOf(Function initial) {
    abstract class AtomicRunnableAddress implements Address, Runnable
    { final AtomicInteger on = new AtomicInteger(0); }
    var addr = new AtomicRunnableAddress() {
    final ConcurrentLinkedQueue mb = new ConcurrentLinkedQueue<>();
    Behavior behavior = m -> (m instanceof Address self) ? Become(initial.apply(self)) : Stay;
    public Address tell(Object msg) { mb.offer(msg); async(); return this; }
    public void run() {
    try { if (on.get() == 1) { var m = mb.poll(); if (m!=null) { behavior = behavior.apply(m).apply(behavior); } }}
    finally { on.set(0); async(); }}
    void async() {
    if (!mb.isEmpty() && on.compareAndSet(0, 1)) {
    try { executorService.execute(this); }
    catch (Throwable t) { on.set(0); throw t; }}}
    };
    return addr.tell(addr);
    }
    }
    }
    evacchi.github.io

    View full-size slide

  15. @evacchi
    What You Will Bring Home
    ● Learn new Java 19 features
    ● Learn an interesting concurrency model
    ● Learn how to run code snippets with JBang

    View full-size slide

  16. @evacchi
    What You Will Bring Home
    ● Learn new Java 19 features
    ● Learn an interesting concurrency model
    ● Learn how to run code snippets with JBang
    ● Learn how to write concise Java program
    with tricks that will make your coworkers mad

    View full-size slide

  17. @evacchi
    Agenda
    ● What is an actor?
    ● Comparison between actor runtimes
    ● Features of Java we will be using

    ● Examples of actors (live coding)
    ● An actor runtime (live coding)
    ● A typed actor runtime (live coding)

    ● An actor-based chat (live coding)
    ● Virtual Threads and Project Loom
    ● A Loom-based chat (live coding)
    Live coding with

    View full-size slide

  18. Actor Definition

    View full-size slide

  19. @evacchi
    Actor Definition
    An actor is a computational entity that, in response to a message it
    receives, can concurrently:
    ● send a finite number of messages to other actors;
    ● create a finite number of new actors;
    ● designate the behavior to be used for the next message it receives.
    "Everything" is an actor.

    View full-size slide

  20. @evacchi
    Actor Model
    ● Modelling stateful systems
    ● Distributed systems (e.g. leveraging location transparency)
    ● IoT (e.g. Digital twins)

    View full-size slide

  21. @evacchi
    Actor Model
    ● Concurrency Model
    ● Simple
    ● "Single-Thread" reasoning
    ● Message-based, "Mailbox"

    View full-size slide

  22. @evacchi
    Implementation
    Function + State + Message Queue

    View full-size slide

  23. @evacchi
    Implementation
    Function + State + Message Queue

    View full-size slide

  24. @evacchi
    Implementation
    Function + State + Message Queue

    View full-size slide

  25. @evacchi
    🖂 ➡ 🖂 🖂 🖂 🖂 🖂 🖂
    Implementation
    Private State
    Behavior
    mailbox

    View full-size slide

  26. @evacchi
    Implementation
    🖂 🖂 🖂 🖂 🖂 🖂 🖂
    Private State
    Behavior

    View full-size slide

  27. @evacchi
    Implementation
    🖂 🖂 🖂 🖂 🖂 🖂
    Private State
    Behavior
    🖂

    View full-size slide

  28. @evacchi
    Implementation
    🖂 🖂 🖂 🖂 🖂 🖂
    Private State
    Behavior
    🖂

    View full-size slide

  29. @evacchi
    Implementation
    🖂 🖂 🖂 🖂 🖂 🖂
    Private State
    Behavior
    🖂
    📤

    View full-size slide

  30. @evacchi
    Implementation
    🖂 🖂 🖂 🖂 🖂 🖂
    Private State
    Behavior
    🖂 🖂 ➡

    View full-size slide

  31. @evacchi
    Messages vs Methods
    ● you send a message to an actor
    ● you invoke a method on an object
    ● however in Smalltalk you send "messages"
    to objects

    View full-size slide

  32. @evacchi
    Messages vs Methods
    ● you send a message to an actor
    ● you invoke a method on an object
    ● however in Smalltalk you send "messages"
    to objects
    ● in fact, some people think that actors
    are "proper" OOP as envisioned by
    Alan Kay

    View full-size slide

  33. https://twitter.com/joeerl/status/1107348549132533760
    @evacchi

    View full-size slide

  34. https://twitter.com/joeerl/status/1107544833911128064
    @evacchi

    View full-size slide

  35. https://twitter.com/joeerl/status/1107544833911128064

    View full-size slide

  36. @evacchi
    Spawning Actors

    View full-size slide

  37. @evacchi
    Vending Machines (FSM)

    View full-size slide

  38. Actor Runtimes

    View full-size slide

  39. @evacchi
    When Scala Roamed The World
    ● Java 8 in 2014
    ● Context: JDK 5/6/7
    ○ Mainstream statically typed OOP programming languages
    were verbose (C++/Java/C#)
    ○ Dynamic languages were more concise (Python/Ruby/Groovy)
    ● Enter Scala
    ○ Static typing
    ○ Dynamic feel / conciseness
    ○ Actor library

    View full-size slide

  40. @evacchi
    When Scala Roamed The World
    ● Context: JDK 5/6/7
    ○ Mainstream statically typed OOP programming languages
    were verbose (C++/Java/C#)
    ○ Dynamic languages were more concise Python/Ruby/Groovy
    ● Enter Scala
    ○ Static typing
    ○ Dynamic feel / conciseness
    ○ Actor library

    View full-size slide

  41. @evacchi
    Akka (Scala)
    case object Ping
    class Pingponger extends Actor {
    var count = 10
    def receive: Any => Unit = {
    case Ping =>
    println(s"${self.path} received ping, count down $count")
    if (this.count > 0) {
    this.count = this.count - 1
    sender() ! Ping
    }
    }
    }
    val system = ActorSystem("pingpong")
    val pinger = system.actorOf(Props[Pingponger](), "pinger")
    val ponger = system.actorOf(Props[Pingponger](), "ponger")
    pinger.tell(Ping, ponger)

    View full-size slide

  42. @evacchi
    Akka (Scala)
    case class Ping(count: Int)
    class Pingponger extends Actor {
    def receive: Any => Unit = {
    case Ping(count) =>
    println(s"${self.path} received ping, count down $count")
    if (count > 0) {
    sender() ! Ping(count - 1)
    }
    }
    }
    val system = ActorSystem("pingpong")
    val pinger = system.actorOf(Props[Pingponger](), "pinger")
    val ponger = system.actorOf(Props[Pingponger](), "ponger")
    pinger.tell(Ping(10), ponger)

    View full-size slide

  43. @evacchi
    Akka (Scala)
    case class Ping(count: Int)
    class Pingponger extends Actor {
    def receive(msg: Any): Unit =
    msg match {
    case Ping(count) =>
    println(s"${self.path} received ping, count down $count")
    if (count > 0) {
    sender() ! Ping(count - 1)
    }
    }
    }
    val system = ActorSystem("pingpong")
    val pinger = system.actorOf(Props[Pingponger](), "pinger")
    val ponger = system.actorOf(Props[Pingponger](), "ponger")
    pinger.tell(Ping(10), ponger)

    View full-size slide

  44. @evacchi
    Akka + Java
    public class MyUntypedActor extends UntypedActor {
    LoggingAdapter log = Logging.getLogger(getContext().system(), this);
    public void onReceive(Object message) throws Exception {
    if (message instanceof Ping) {
    Ping p = (Ping) message;
    if (p.count() > 0) {
    log.info("Received ping : " + p.count());
    getSender().tell(new Ping(p.count() - 1), getSelf());
    }
    }
    }

    View full-size slide

  45. @evacchi
    Scala
    Groovy
    Ruby
    Python
    Java

    View full-size slide

  46. @evacchi
    Erlang
    pingponger(Name, Main) ->
    receive
    {ping, Count, Ping_PID} ->
    io:format("~s received ping, count down ~w~n", [Name, Count]),
    if Count > 0 ->
    Ping_PID ! {ping, Count - 1, self()},
    pingponger(Name, Main);
    true ->
    exit ("done")
    end
    end.
    main(_) ->
    Ping1_PID = spawn(fun() -> pingponger("pinger", self()) end),
    Ping2_PID = spawn(fun() -> pingponger("ponger", self()) end),
    Ping1_PID ! {ping, 10, Ping2_PID}.

    View full-size slide

  47. @evacchi
    Elixir
    defmodule Main do
    def pingponger(name) do
    receive do
    {:ping, count, sender} ->
    IO.puts "#{name} received ping, count down #{count}"
    if count > 0 do
    send sender, {:ping, count - 1, self()}
    pingponger(name)
    else
    :ok
    end
    end
    end
    end
    pid1 = spawn fn -> Main.pingponger("pinger") end
    pid2 = spawn fn -> Main.pingponger("ponger") end
    send pid1, {:ping, 10, pid2}

    View full-size slide

  48. @evacchi
    Scala
    Groovy
    Ruby
    Python
    Java
    Erlang
    Elixir

    View full-size slide

  49. @evacchi
    Akka + Java
    public class MyUntypedActor extends UntypedActor {
    LoggingAdapter log = Logging.getLogger(getContext().system(), this);
    public void onReceive(Object message) throws Exception {
    if (message instanceof Ping) {
    Ping p = (Ping) message;
    if (p.count() > 0) {
    log.info("Received ping : " + p.count());
    getSender().tell(new Ping(p.count() - 1), getSelf());
    }
    }
    } Can we improve over this?

    View full-size slide

  50. Tools Of The Trade

    View full-size slide

  51. @evacchi
    (Ab)using Language Defaults To Reduce Noise
    public class Main {
    public static final String HELLO = "hello world";
    public static void main(String[] args) {
    System.out.println(HELLO);
    }
    }

    View full-size slide

  52. @evacchi
    (Ab)using Language Defaults To Reduce Noise
    public class Main {
    public static final String HELLO = "hello world";
    public static void main(String[] args) {
    System.out.println(HELLO);
    }
    }

    View full-size slide

  53. @evacchi
    (Ab)using Language Defaults To Reduce Noise
    public interface Main {
    public static final String HELLO = "hello world";
    public static void main(String[] args) {
    System.out.println(HELLO);
    }
    }

    View full-size slide

  54. @evacchi
    (Ab)using Language Defaults To Reduce Noise
    public interface Main {
    public static final String HELLO = "hello world";
    public static void main(String[] args) {
    System.out.println(HELLO);
    }
    }

    View full-size slide

  55. @evacchi
    (Ab)using Language Defaults To Reduce Noise
    import static java.lang.System.*;
    public interface Main {
    public static final String HELLO = "hello world";
    public static void main(String[] args) {
    System.out.println(HELLO);
    }
    }

    View full-size slide

  56. @evacchi
    (Ab)using Language Defaults To Reduce Noise
    import static java.lang.System.*;
    interface Main {
    String HELLO = "hello world";
    static void main(String... args) { out.println(HELLO); }
    }

    View full-size slide

  57. https://openjdk.org/projects/amber/design-notes/on-ramp

    View full-size slide

  58. public class HelloWorld {
    public static void main(String[] args) {
    System.out.println("Hello World");
    }
    }
    @evacchi

    View full-size slide

  59. public class HelloWorld {
    public static void main(String[] args) {
    System.out.println("Hello World");
    }
    }
    @evacchi

    View full-size slide

  60. public class HelloWorld {
    public static void main(String[] args) {
    System.out.println("Hello World");
    }
    }
    void main() {
    println("Hello World");
    }
    @evacchi

    View full-size slide

  61. Is This
    Code-Golfing?
    me
    recent Java
    syntax

    View full-size slide

  62. @evacchi
    More “Code Golfing”
    public class Auth {
    private final String login;
    private final String token;
    public Auth(String login, String token) {
    this.login = login;
    this.token = token;
    }
    public String login() { return this.login; }
    public String token() { return this.token; }
    public boolean equals(Object o) { ... }
    public int hashCode() { return Objects.hash(login, token); }
    public String toString() { ... }
    }
    public class Anon {
    private final String email;
    public Anon(String email) { this.email = email; }
    public String email() { return this.email; }
    public boolean equals(Object o) { ... }
    public int hashCode() { ... }
    public String toString() { ... }
    }

    View full-size slide

  63. @evacchi
    More “Code Golfing”
    public void onReceive(Object message) throws Exception {
    if (message instanceof Auth) {
    Auth a = (Auth) message;
    check(a.login());
    if (validate(a.login(), a.token())) {
    // grant full access
    } else {
    // error
    }
    } else if (message instanceof Anon) {
    Anon a = (Anon) message;
    // grant guest access
    } else
    unhandled(message);
    }

    View full-size slide

  64. @evacchi
    More “Code Golfing”
    public void onReceive(Object message) throws Exception {
    if (message instanceof Auth) {
    Auth a = (Auth) message;
    check(a.login());
    if (validate(a.login(), a.token())) {
    // grant full access
    } else {
    // error
    }
    } else if (message instanceof Anon) {
    Anon a = (Anon) message;
    // grant guest access
    } else
    unhandled(message);
    }

    View full-size slide

  65. @evacchi
    Enhanced instanceof
    public void onReceive(Object message) throws Exception {
    if (message instanceof Auth a) {
    check(a.login());
    if (validate(a.login(), a.token())) {
    // grant full access
    } else {
    // error
    }
    } else if (message instanceof Anon a) {
    // grant guest access
    } else
    unhandled(message);
    }
    pattern matching

    View full-size slide

  66. @evacchi
    More “Code Golfing”
    public class Auth {
    private final String login;
    private final String token;
    public Auth(String login, String token) {
    this.login = login;
    this.token = token;
    }
    public String login() { return this.login; }
    public String token() { return this.token; }
    public boolean equals(Object o) { ... }
    public int hashCode() { return Objects.hash(login, token); }
    public String toString() { ... }
    }
    public class Anon {
    private final String email;
    public Anon(String email) { this.email = email; }
    public String email() { return this.email; }
    public boolean equals(Object o) { ... }
    public int hashCode() { ... }
    public String toString() { ... }
    }

    View full-size slide

  67. @evacchi
    Records
    public record Auth(String login, String token) {}
    public record Anon(String email) {}

    View full-size slide

  68. @evacchi
    Enhanced instanceof
    public void onReceive(Object message) throws Exception {
    if (message instanceof Auth(var login, var token)) {
    check(login);
    if (validate(login, token)) {
    // grant full access
    } else {
    // error
    }
    } else if (message instanceof Anon(String email)) {
    // grant guest access
    } else
    unhandled(message);
    }
    deconstruction patterns

    View full-size slide

  69. @evacchi
    More “Code Golfing”
    public void onReceive(Object message) throws Exception {
    switch (message) {
    case Auth(var login, var token) -> {
    check(login);
    if (validate(login, token)) {
    // grant full access
    } else {
    // error
    }
    }
    case Anon(var email) -> { /* guest access */ };
    default -> unhandled(message);
    }
    }

    View full-size slide

  70. @evacchi
    More “Code Golfing”
    public void onReceive(Object message) throws Exception {
    switch (message) {
    case Auth(var login, var token) -> {
    check(login);
    if (validate(login, token)) {
    // grant full access
    } else {
    // error
    }
    }
    case Anon(var email) -> { /* guest access */ };
    default -> unhandled(message);
    }
    }
    Improved Switch

    View full-size slide

  71. @evacchi
    More “Code Golfing”
    public void onReceive(Object message) throws Exception {
    switch (message) {
    case Auth(var login, var token) -> {
    check(login);
    if (validate(login, token)) {
    // grant full access
    } else {
    // error
    }
    }
    case Anon(var email) -> { /* guest access */ };
    default -> unhandled(message);
    }
    }
    Records

    View full-size slide

  72. @evacchi
    More “Code Golfing”
    public void onReceive(Object message) throws Exception {
    switch (message) {
    case Auth(var login, var token) -> {
    check(login);
    if (validate(login, token)) {
    // grant full access
    } else {
    // error
    }
    }
    case Anon(var email) -> { /* guest access */ };
    default -> unhandled(message);
    }
    }
    deconstruction patterns

    View full-size slide

  73. @evacchi
    More “Code Golfing”
    public void onReceive(Object message) throws Exception {
    switch (message) {
    case Auth(var login, var token) -> {
    check(login);
    if (validate(login, token)) {
    // grant full access
    } else {
    // error
    }
    }
    case Anon(var email) -> { /* guest access */ };
    default -> unhandled(message);
    }
    }
    var
    pattern

    View full-size slide

  74. @evacchi
    More “Code Golfing”
    public void onReceive(Object message) throws Exception {
    switch (message) {
    case Auth(var login, var token) -> {
    check(login);
    if (validate(login, token)) {
    // grant full access
    } else {
    // error
    }
    }
    case Anon(var email) -> { /* guest access */ };
    default -> unhandled(message);
    }
    }

    View full-size slide

  75. @evacchi
    Records
    public record Auth(String login, String token) {}
    public record Anon(String email) {}

    View full-size slide

  76. @evacchi
    Sealed Hierarchies
    sealed interface LoginInfo {}
    public record Auth(String login, String token) implements LoginInfo {}
    public record Anon(String email) implements LoginInfo {}

    View full-size slide

  77. @evacchi
    Exhaustive Pattern Matching
    public void onReceive(LoginInfo message) throws Exception {
    switch (message) {
    case Auth(var login, var token) -> {
    check(login);
    if (validate(login, token)) {
    // grant full access
    } else {
    // error
    }
    }
    case Anon(var email) -> { /* guest access */ };
    }
    }
    Sealed Type Hierarchy
    No Default Case!

    View full-size slide

  78. @evacchi
    Scala
    def onReceive(Any: message): Unit {
    message match {
    case Auth(login, token) => {
    check(login)
    if (validate(login, token)) {
    // grant full access
    } else {
    // error
    }
    }
    case Anon(email) => { /* guest access */ };
    }
    }

    View full-size slide

  79. @evacchi
    Akka + Java + Pattern Matching
    public class MyUntypedActor extends UntypedActor {
    LoggingAdapter log = Logging.getLogger(getContext().system(), this);
    public void onReceive(Object message) throws Exception {
    switch (message) {
    case String m -> {
    log.info("Received String message: {}", message);
    getSender().tell(message, getSelf());
    }
    default -> unhandled(message);
    }
    }
    }

    View full-size slide

  80. @evacchi
    Akka + Java
    static class Pingponger extends AbstractActor {
    @Override
    public Receive createReceive() {
    return receiveBuilder()
    .match(
    Ping.class,
    ping -> {
    out.println(getSelf().path() + " received ping, count down " + ping.getCount());
    if (ping.getCount() > 0) {
    getSender().tell(new Ping(ping.getCount() - 1), getSelf());
    }
    })
    .build();
    }
    }
    public static void main(String... args) {
    ActorSystem system = ActorSystem.apply("pingpong");
    ActorRef pinger = system.actorOf(Props.create(Pingponger.class), "pinger");
    ActorRef ponger = system.actorOf(Props.create(Pingponger.class), "ponger");
    pinger.tell(new Ping(10), ponger);
    }

    View full-size slide

  81. gist.github.com/viktorklang/2557678

    View full-size slide

  82. @evacchi
    Agenda
    ● What is an actor?
    ● Comparison between actor runtimes
    ● Features of Java we will be using

    ● Examples of actors (live coding)
    ● An actor runtime (live coding)
    ● A typed actor runtime (live coding)

    ● An actor-based chat (live coding)
    ● Virtual Threads and Project Loom
    ● A Loom-based chat (live coding)
    Live coding with

    View full-size slide

  83. Live Coding with

    View full-size slide

  84. @evacchi
    My First Actor

    View full-size slide

  85. @evacchi
    Vending Machines (FSM)

    View full-size slide

  86. Closures vs Classes

    View full-size slide

  87. @evacchi
    Implementation
    Function + State + Message Queue

    View full-size slide

  88. @evacchi
    Closures vs Classes
    The venerable master Qc Na was walking with his student, Anton.
    Hoping to prompt the master into a discussion, Anton said
    “Master, I have heard that objects are a very good thing - is this true?”
    Qc Na looked pityingly at his student and replied…

    View full-size slide

  89. @evacchi
    Closures vs Classes
    “Foolish pupil – objects are merely a poor man’s closures.”

    View full-size slide

  90. @evacchi
    Closures vs Classes
    Chastised, Anton took his leave from his master and returned to his cell,
    intent on studying closures. He carefully read the entire "Lambda: The
    Ultimate..." series of papers and its cousins, and implemented a small
    Scheme interpreter with a closure-based object system. He learned much, and
    looked forward to informing his master of his progress.

    View full-size slide

  91. @evacchi
    Closures vs Classes
    On his next walk with Qc Na, Anton attempted to impress his master by
    saying “Master, I have diligently studied the matter, and now understand
    that objects are truly a poor man’s closures.” Qc Na responded by hitting
    Anton with his stick, saying…

    View full-size slide

  92. @evacchi
    Closures vs Classes
    “When will you learn? Closures are a poor man's object.”

    View full-size slide

  93. @evacchi
    Closures vs Classes
    At that moment, Anton became enlightened.
    http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg03277.html

    View full-size slide

  94. @evacchi
    Agenda
    ● What is an actor?
    ● Comparison between actor runtimes
    ● Features of Java we will be using

    ● Examples of actors (live coding)
    ● An actor runtime (live coding)
    ● A typed actor runtime (live coding)

    ● An actor-based chat (live coding)
    ● Virtual Threads and Project Loom
    ● A Loom-based chat (live coding)
    Live coding with

    View full-size slide

  95. Write You a Chat

    View full-size slide

  96. @evacchi
    Server

    View full-size slide

  97. @evacchi
    Client Manager

    View full-size slide

  98. @evacchi
    Client Manager

    View full-size slide

  99. @evacchi
    Thou Shall Not Block!

    View full-size slide

  100. @evacchi
    Green Threads
    ● in the Java 1.0 days, some JVMs "green" (user-mode) threads.
    ● The green threads of the 90s still had large, monolithic stacks.
    ● A product of their time
    ○ systems were single-core
    ○ OSes did not have thread support at all.
    https://www.infoq.com/articles/java-virtual-threads/

    View full-size slide

  101. @evacchi
    Virtual Threads
    ● Virtual threads: only superficial similarity to Green Threads
    ● More in common with user-mode threads in Go or Erlang
    ● However: semantically identical to java.lang.Thread

    View full-size slide

  102. @evacchi
    Virtual Threads
    ● Virtual threads: only superficial similarity to Green Threads
    ● More in common with user-mode threads in Go or Erlang
    ● However: semantically identical to java.lang.Thread

    View full-size slide

  103. @evacchi
    Green Threads
    ● Solaris 2.6 software
    ● the green threads library was user-level
    ● the Solaris system could process only one green thread at a time,
    ● Solaris handled the Java runtime as a many-to-one threading implementation
    ● Java applications could not interoperate with existing MT applications in the
    Solaris environment.
    ● Java threads could not run in parallel on multiprocessors.
    ● An MT Java application could not harness true OS concurrency for faster
    applications on either uniprocessors or multiprocessors.
    Green threads library was replaced with native Solaris threads for Java on the Solaris 2.6
    platform; this is carried forward on the Solaris 7 and Solaris 8 platforms.
    https://docs.oracle.com/cd/E19455-01/806-3461/6jck06gqe/

    View full-size slide

  104. @evacchi
    Loom
    https://wiki.openjdk.org/display/loom/Main
    “Project Loom is intended to explore, incubate and
    deliver Java VM features and APIs built on top of them
    for the purpose of supporting easy-to-use,
    high-throughput lightweight concurrency and new
    programming models on the Java platform.”

    View full-size slide

  105. @evacchi
    Loom
    ● Virtual Threads are mounted on platform threads
    (carrier threads)
    ● Yield in std library

    View full-size slide

  106. https://www.youtube.com/watch?v=449j7oKQVkc

    View full-size slide

  107. @evacchi
    Thou Shall Not Block!

    View full-size slide

  108. @evacchi
    Thou Shall Not Block!

    View full-size slide

  109. Write You
    a Loom Chat

    View full-size slide

  110. Game of Loom:
    implementation patterns and
    performance implications
    playing with virtual threads
    by Mario Fusco
    @mariofusco Learn More
    This Thursday!

    View full-size slide

  111. @evacchi
    bit.ly/actor19

    View full-size slide