简体   繁体   English

实施事件驱动的轻量级线程

[英]Implementing event-driven lightweight threads

Inspired by libraries like Akka and Quasar I started wondering how these actually work "under the hood". 受Akka和Quasar之类的图书馆的启发,我开始想知道它们实际上是如何“在后台”工作的。 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. 我仍然想学习如何使用Java 8实现(最多)我自己的“事件驱动的轻量级线程”的非常基本的版本。

I'm quite familiar with Akka as a library, and I have an intermediate understanding about concurrency on the JVM. 我对Akka作为一个库非常熟悉,并且对JVM的并发有一个中间的了解。

Could anyone point me to some literature covering this, or try to describe the concepts involved? 谁能指出我的一些有关这方面的文献,还是试图描述其中涉及的概念?

In Akka it works like this: 在Akka中,它的工作方式如下:

  • 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) 当某些代码调用ActorRef.tell(msg)msg将放入引用的actor的邮箱中(尽管这不足以运行任何东西)
  • 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 当调度程序正在执行处理邮箱的任务时,将调用actor处理另一个消息
  • Messages in this mailbox up to the count specified in akka.actor.throughput are handled by this one task in one go. 此邮箱一次完成处理此邮箱中的邮件(直到akka.actor.throughput中指定的数量)。 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, ie 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. 默认情况下,Akka在底层使用JDK的ForkJoinPool,这是一个非常复杂的窃取线程池的实现。

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/ 我是Chronicle Queue的架构师,您可以在我的博客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. 降低分配率以提高GC之间的吞吐量,并减少GC的影响。

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) 对于我正在使用的某些系统,您可以用Java实现30微秒的延迟(网络数据包输入到网络数据包输出)

In Akka, 在阿卡

1.Actor system allocates the threads from thread pool to actors that have messages to process. 1.Actor系统将线程池中的线程分配给需要处理消息的actor。

2.When the actor has no messages to process,thread is released and allocated to other actors that have messages to process 2.当actor没有消息要处理时,线程被释放并分配给其他有消息要处理的actor

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. 通过这种方式,异步参与者系统可以使用相同数量的资源处理更多并发请求,因为有限数量的线程(线程池)在等待I / O操作完成时永远不会处于空闲状态。

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 有关更多信息,您可以下载并查看此电子书https://info.lightbend.com/COLL-20XX-Designing-Reactive-Systems_RES-LP.html?lst=BL&_ga=1.214533079.1169348714.1482593952

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM