我最近读到了Quasar,它为 JVM 提供了“轻量级”/类似 Go 的“用户模式”线程(它也有一个受 Erlang 启发的 Actor 系统,比如 Akka,但这不是主要问题)
例如:
package jmodern;
import co.paralleluniverse.fibers.Fiber;
import co.paralleluniverse.strands.Strand;
import co.paralleluniverse.strands.channels.Channel;
import co.paralleluniverse.strands.channels.Channels;
public class Main {
public static void main(String[] args) throws Exception {
final Channel<Integer> ch = Channels.newChannel(0);
new Fiber<Void>(() -> {
for (int i = 0; i < 10; i++) {
Strand.sleep(100);
ch.send(i);
}
ch.close();
}).start();
new Fiber<Void>(() -> {
Integer x;
while((x = ch.receive()) != null)
System.out.println("--> " + x);
}).start().join(); // join waits for this fiber to finish
}
}
据我了解,上面的代码不会产生任何 JVM / 内核线程,所有这些都是在用户模式线程中完成的(或者他们声称),这应该更便宜(如果我理解正确的话,就像 Go 协程一样)
我的问题是 - 据我了解,在 Akka 中,一切仍然基于 JVM 线程,大多数情况下映射到本机 OS 内核线程(例如 POSIX 系统中的 pthreads),例如据我所知有没有用户模式线程/像 Akka 中的协同程序/轻量级线程一样,我理解正确吗?
如果是这样,那么您知道这是否是一种设计选择吗?或者未来在 Akka 中是否有类似 go 的轻量级线程的计划?
我的理解是,如果你有一百万个 Actor,但其中大多数是阻塞的,那么 Akka 可以用更少的物理线程来处理它,但是如果它们中的大多数是非阻塞的,你仍然需要系统的一些响应(例如服务百万个小请求流式传输一些数据)然后我可以看到用户模式线程实现的好处,它可以允许更多的“线程”以较低的创建切换和终止的成本存活(当然唯一的好处是平均分配响应许多客户,但响应能力仍然很重要)
我的理解或多或少是正确的?如果我错了,请纠正我。
*我可能完全将用户模式线程与 go/co-routines 和轻量级线程混淆了,上面的问题依赖于我对它们都是相同的理解不足。