【发布时间】:2014-05-01 19:34:06
【问题描述】:
我最近读到了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 和轻量级线程混淆了,上面的问题依赖于我对它们都是相同的理解不足。
【问题讨论】:
-
这是我在使用 Python 时所记得的。这不是一个直接的答案,但它可能有用。用户/轻量级线程和实际系统线程都有其用途。归根结底,两者都提供并发性,但只有系统线程提供并行性。因此,如果您正在进行大量计算,您将不会从使用用户线程中获得任何提升,但您会从系统线程中获得任何提升。在另一种情况下,您只有一个 CPU 内核并且您想要一台服务器,使用用户线程是唯一的解决方案。
-
是的,这也是我所理解的,例如用户线程仅适用于提供 CPU 的“良好利用率”,例如在有时会阻塞 IO 的 2 个用户线程之间切换比使用完整线程便宜。你没有得到并行性,但如果我理解正确,你确实可以更好地利用 CPU
-
请看我的回答,它会有所帮助:stackoverflow.com/questions/29680718/…
标签: java multithreading scala akka quasar