Franz
Franz

Reputation: 2003

Implementing event-driven lightweight threads

Inspired by libraries like Akka and Quasar I started wondering how these actually work "under the hood". I'm aware that it is most likely very complex and that they all work quite different from each other.

I would still like to learn how I would go to implement a (at most) very basic version of my own "event-driven lightweight threads" using Java 8.

I'm quite familiar with Akka as a library, and I have an intermediate understanding about concurrency on the JVM.

Could anyone point me to some literature covering this, or try to describe the concepts involved?

Upvotes: 1

Views: 571

Answers (3)

jrudolph
jrudolph

Reputation: 8367

In Akka it works like this:

  • An actor is a class that bundles a mailbox with the behavior to handle messages
  • When some code calls ActorRef.tell(msg), the msg is put into the mailbox of the referenced actor (though, this wouldn't be enough to run anything)
  • A task is queued on the dispatcher (a thread pool basically) to handle messages in the mailbox
  • When another message comes in and the mailbox is already queued, it doesn't need to be scheduled again
  • When the dispatcher is executing the task to handle the mailbox, the actor is called to handle one message after the other
  • Messages in this mailbox up to the count specified in akka.actor.throughput are handled by this one task in one go. If the mailbox still has messages afterwards, another task is scheduled on the dispatcher to handle the remaining messages. Afterwards the tasks exits. This ensures fairness, i.e. that the thread this mailbox is run on isn't indefinitely blocked by one actor.

So, there are basically two work queues:

  1. The mailbox of an actor. These messages need to be processed sequentially to ensure the contract of actors.
  2. The queue of the dispatcher. All of the tasks in here can be processed concurrently.

The hardest part of writing this efficiently is the thread pool. In the thread pool a bunch of worker threads need to access their task queue in an efficient way. By default, Akka uses JDK's ForkJoinPool under-the-hood which is a very sophisticated work-stealing thread pool implementation.

Upvotes: 2

Advika
Advika

Reputation: 595

In Akka,

1.Actor system allocates the threads from thread pool to actors that have messages to process.

2.When the actor has no messages to process,thread is released and allocated to other actors that have messages to process

This way asynchronous actor systems can handle many more concurrent requests with the same amount of resources since the limited number of threads(thread pool) never sit idle while waiting for I/O operations to complete.

For more information you can download & check this e-book https://info.lightbend.com/COLL-20XX-Designing-Reactive-Systems_RES-LP.html?lst=BL&_ga=1.214533079.1169348714.1482593952

Upvotes: 1

Peter Lawrey
Peter Lawrey

Reputation: 533820

Could anyone point me to some literature covering this,

I am the architect for Chronicle Queue and you can read how it is used and works here on my blog https://vanilla-java.github.io/tag/Microservices/

try to describe the concepts involved?

You have;

  • above all, make your threads faster and light weight by doing less work.
  • try to deal with each event as quickly as possible to keep latency low.
  • batch when necessary but keep it to a minimum. Batching add latency but can help improve maximum throughput.
  • Identify the critical path. Keep this as short as possible, moving anything blocking or long running to asynchronous thread/processes.
  • keep hops to a minimum, either between threads, processes or machines.
  • keep allocation rates down to improve throughput between GCs, and reduce the impact of GCs.

For some of the systems I work on you can achieve latencies of 30 micro-seconds in Java (network packet in to network packet out)

Upvotes: 1

Related Questions