我已经搜索了一些网站,以帮助理解这一点,但是没有找到任何超级明确的内容,所以我想我会发布我的用例,看看是否有人可以解决这些问题。
我有一个关于在akka中用于io操作时jvm线程vs os线程的扩展的问题。来自akka网站:
Akka支持事件驱动的轻量级线程的调度程序,允许在单个工作站上创建数百万个线程,以及基于线程的Actors,其中每个调度程序都绑定到专用的OS线程。
基于事件的Actors当前每个Actor消耗约600个字节,这意味着您可以在4 G RAM上创建超过650万个Actors。
在这种情况下,你能否帮我理解在只有1个处理器的工作站上的重要性(为简单起见)。因此,对于我的示例用例,我想获取1000个“用户”的列表,然后查询数据库(或多个)以获取有关每个用户的各种信息。因此,如果我将这些'get'任务分配给一个actor,并且该actor将要执行IO,那么该actor是否会根据工作站的os线程限制进行阻塞?
akka演员模型如何让我在这样的场景中解脱?我知道我可能遗漏了一些东西,因为我对vm线程与os线程的交互不是很了解,所以如果这里有一个聪明的人可以为我拼出来,那就太棒了。
如果我使用Futures,我是否需要使用await()或get()来阻止并等待回复?
在我的使用案例中,无论演员如何,它最终只是'感觉'就像我正在制作1000个顺序数据库请求一样?
如果代码片段有助于我理解这一点,那么Java会更受欢迎,因为我仍然需要加快scala语法的速度 - 但这是一个很好的明确文本解释,说明这些数百万个线程如何在单个处理器计算机上进行互操作做数据库IO也没问题。
答案 0 :(得分:15)
很难弄清楚你在这里问的是什么,但这里有一些指示:
如果您在现代JVM上运行,Java线程和OS线程之间通常存在一对一的关系。 (IIRC,Solaris允许您以不同的方式执行此操作......但这是例外。)
使用线程获得的实际并行度,或者构建在线程之上的任何内容都受到应用程序可用的处理器/核心数量的限制。除此之外,您会发现并非所有线程都在任何特定时刻执行。
如果你有1000个Actors都试图“同时”访问数据库,那么它们中的大多数实际上都在等待数据库本身,或者在线程调度程序上。这相当于制作1000个连续请求(即严格序列化)将取决于数据库以及演员正在进行的查询/更新。
最重要的是,计算机系统对可用资源有严格的限制;例如处理器数量,处理器速度,内存带宽,磁盘访问时间,网络带宽等。您可以设计一个应用程序,使其智能地了解它使用可用资源的方式,但是你不能让它使用比实际更多的资源是
在阅读你引用的文字时,在我看来它正在谈论两种不同类型的演员:
基于线程的actor与线程有1对1的关系。你无法在4Gb内存中拥有数百万这样的演员。
基于事件的演员的工作方式不同。它们总是坐在队列中等待事件发生,而不是始终拥有一个线程。当发生这种情况时,事件处理线程将从队列中获取actor并执行与该事件相关联的“动作”。当动作结束时,线程移动到另一个actor /事件对。
引用的文字说基于事件的 actor的内存开销是~600字节。它们不包含事件线程...因为事件线程由多个actor共享。
现在我不是Scala / Actors的专家,但很明显在使用基于事件的actor时应该避免某些事情。例如,您应该避免直接与外部数据库交谈,因为这可能会阻止事件处理线程。
答案 1 :(得分:8)
我认为那里可能会有拼写错误。我想他们的意思是说:
Akka支持事件驱动的轻量级演员的调度员, 允许在单个工作站上创建数百万个 actor ,以及基于线程的Actors,其中每个 actor 都绑定到专用的OS线程。
事件驱动的actor使用线程池 - 所有(可能数百万)actor都共享相同的线程池。我对Akka演员并不熟悉,但通常你不想用事件驱动的演员阻止I / O,否则你可能会导致饥饿。