1

受到 Akka 和 Quasar 等库的启发,我开始想知道这些库实际上是如何“在幕后”工作的。我知道这很可能非常复杂,并且它们的工作方式彼此完全不同。

我仍然想了解如何使用 Java 8 实现我自己的“事件驱动的轻量级线程”的(至多)非常基本的版本。

我对 Akka 作为一个库非常熟悉,并且对 JVM 上的并发性有一个中等的了解。

任何人都可以向我指出一些涵盖这一点的文献,或者尝试描述所涉及的概念吗?

4

3 回答 3

2

在 Akka 中,它是这样工作的:

  • 演员是将邮箱与处理消息的行为捆绑在一起的类
  • 当一些代码调用ActorRef.tell(msg)时,msg被放入被引用actor的邮箱中(虽然,这不足以运行任何东西)
  • 任务在调度程序(基本上是线程池)上排队以处理邮箱中的消息
  • 当另一条消息进来并且邮箱已经排队时,不需要再次调度
  • 当调度程序正在执行处理邮箱的任务时,会调用actor来处理一条又一条消息
  • 此邮箱中指定数量的邮件akka.actor.throughput将由这一任务一次性处理。如果邮箱之后仍有消息,则调度程序会安排另一个任务来处理剩余的消息。之后任务退出。这确保了公平性,即运行此邮箱的线程不会被一个参与者无限期地阻塞。

所以,基本上有两个工作队列:

  1. 演员的邮箱。这些消息需要按顺序处理,以确保参与者的合同。
  2. 调度程序的队列。这里的所有任务都可以同时处理。

高效编写此代码最难的部分是线程池。在线程池中,一堆工作线程需要以一种有效的方式访问它们的任务队列。默认情况下,Akka 在后台使用 JDK 的 ForkJoinPool,这是一个非常复杂的工作窃取线程池实现。

于 2017-02-07T12:30:31.223 回答
1

谁能给我指出一些关于这个的文献,

我是 Chronicle Queue 的架构师,您可以在我的博客https://vanilla-java.github.io/tag/Microservices/上阅读它的使用和工作方式

尝试描述所涉及的概念?

你有;

  • 最重要的是,通过更少的工作让你的线程更快更轻。
  • 尝试尽快处理每个事件以保持低延迟。
  • 必要时分批,但保持在最低限度。批处理会增加延迟,但有助于提高最大吞吐量。
  • 确定关键路径。保持尽可能短,将任何阻塞或长时间运行的东西移至异步线程/进程。
  • 在线程、进程或机器之间将跳数保持在最低限度。
  • 降低分配率以提高 GC 之间的吞吐量,并减少 GC 的影响。

对于我工作的一些系统,您可以在 Java 中实现 30 微秒的延迟(网络数据包输入到网络数据包输出)

于 2017-02-04T12:07:34.200 回答
1

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

于 2017-02-06T09:08:40.273 回答