我试图了解Actors和线程定义的差异。有些文章称actor是轻量级线程,而其他文章则声明actor不是线程。我也明白一个线程可以运行多个actor。我很困惑如何将角色与线程完全区分开来。请帮助我理解,谢谢!
答案 0 :(得分:7)
Actors 处于更高的抽象级别。
线程是一个JVM概念,而 Actor 是在JVM中运行的普通java类,因此问题不在于 Actor vs线程,更多关于 Actor如何使用线程。
什么是演员?
在一个非常简单的层面上, Actor 是一个接收消息的实体,一次一个,并对这些消息做出反应。
Actor如何使用线程?
当Actor收到消息时,它会执行一些操作作为响应。 action 代码如何在JVM中运行?同样,如果只是这种情况,您可以在当前线程上对执行 action 任务的Action进行映像。此外, Actor 可能决定在线程池上执行 action 任务。只要 Actor 确保一次只处理一条消息,这并不重要。
答案 1 :(得分:3)
老实说,他们真的没有多少关系,所以很难谈论他们之间的区别。这就像谈论丰田凯美瑞和蓝色的区别。我试图了解Actors和线程定义的差异。
Actor是一个独立的封装实体,它完全通过发送消息与其他自包含的封装实体进行通信。
现在,如果这听起来与 Object 的定义完全相同,那么你是对的! Actors和Objects之间存在着深刻的联系:演员模型计算由Carl Hewitt构思,部分基于早期Smalltalks的消息导向执行(Smalltalk-71,Smalltalk-72)。反过来,Alan Kay引用了PLANNER'目标导向执行对Smalltalk的消息导向执行具有重大影响...... PLANNER又由Carl Hewitt设计。 (PLANNER也是Prolog的前身,后者又是Erlang的前身; Erlang基于Prolog,最初是Prolog的一个库,第一个实现是用Prolog编写的。)另外,还有Carl Hewitt和Alan Kay引用Vint Cerf和Bob Kahn的早期工作,以后会成为互联网的灵感来源,他们都受到大自然的启发,物理学家Carl Hewitt和微生物学Alan Alan。因此,深层次的联系和相似之处并不令人惊讶。
演员和物体几乎是一回事。我们通常期望面向对象系统中的消息发送是同步的,即时的,可靠的和有序的,而对于Actors没有这样的保证。这是Actors和Objects之间的主要区别:Actors是Message可能会丢失,重新排序,需要很长时间并且是异步的对象。 (唯一的保证是消息可能会被传递最多一次。)此外,消息的接收者通常没有对发件人的隐式引用,因此如果Receiver想要回复消息,发件人需要将自己的引用与Message一起传递(与典型的面向对象系统不同,我总是return
向发件人发送内容。
一个演员可以做三件事,完全这三件事,仅此而已:
请注意,要向Actor发送消息,您需要拥有Actor的地址。您只能将消息发送到地址。一个Actor可能有多个地址,多个Actors可能隐藏在一个地址后面。地址是不可伪造的,你不能自己构建地址,你必须把它交给你。 (这与C中的指针有重要区别,更像是Java中的对象引用。)
在Carl Hewitt本人和Erik Meijer之间有关于微软Channel9社区网站上的演员的白板会议(大部分)非常精彩:Hewitt, Meijer and Szyperski: The Actor Model (everything you wanted to know, but were afraid to ask)。它以其他方式解释了演员背后的基本思想以及演员的基本公理。
还邀请Carl Hewitt在斯坦福大学的EE380计算机系统学术讨论会上发表演讲,在那里他谈到了How to Program the Many Cores For Inconsistency Robustness,其中包括对演员的介绍。
线程,OTOH只是执行的一部分。它们本质上只是一个指令指针和一个调用堆栈。特别是,线程没有内存(自己的)。进程的所有线程共享相同的内存。这意味着,一个行为不当的线程可能会崩溃所有进程的线程,并且必须小心控制对此共享内存的所有访问。
有些文章称actor是轻量级线程,而其他文章则声明actor不是线程。我也明白一个线程可以运行多个actor。
您正在混淆Actor的概念和可能的实现。
现有环境中Actors的一个非常简单的实现方法是使每个Actor都成为一个进程。例如,BEAM(Erlang的主要实现)是如何工作的。这是有效的,因为在BEAM上,流程非常便宜且轻巧;一个过程只重约300字节,10年前便宜的32位单核笔记本电脑上可能有数千万个进程。例如,这将 与Windows进程一起工作,更多昂贵。
在JVM上还有一个Erlang实现(称为Erjang),它使用Kilim,这是JVM上使用字节码重写的非常轻量级的Actors的实现。 (请注意,Erjang和Kilim似乎已经死了。)
如果要在线程上实现Actors,则存在Actors完全隔离而Threads完全共享的问题。所以,你需要以某种方式提供这种隔离。
在诸如JVM之类的系统上实现Actors的常用方法是将Actors实现为对象,然后将它们安排在线程池上运行以获取异步属性。这就是Akka的工作原理。
答案 2 :(得分:2)
我强烈建议您先阅读官方文档: https://doc.akka.io/docs/akka/current/scala/general/actors.html
在幕后,Akka将在一组真实线程上运行多组actor,通常许多actor共享一个线程,一个actor的后续调用最终可能会在不同的线程上进行处理。 Akka确保此实现细节不会影响处理actor状态的单线程。
答案 3 :(得分:0)
线程是一个“活动序列” - 独立于特定对象。它可以执行属于任意对象的代码。
而演员是关于“拥有”其自己的“活动序列”的特定对象。但请注意,此actor序列不一定是线程。与此相反的!
从实现方面来看,可以使用一个线程来驱动许多actor对象。