java actor模型和消息传递实现分析
Actor模型是一种基于协程的消息传递模型,在并行计算和并发的消息传递中有很好的性能表现。一般的actor模块框架提供了超轻量级的线程和工具,可以在这些线程之间进行快速、安全、零复制的消息传递。在elang,ruby,lua等语言中都是直接在VM级别支持协程,VM帮你做context的保存和恢复。而在java中,却没有内置actor模型实现,但是有几个开源框架也模拟了actor模型的实现。
基于 actor 的系统 通过实现一种消息传递 模式,使并行处理更容易编码。在此模式中,系统中的每个 actor 都可接收消息;执行该消息所表示的操作;然后将消息发送给其他 actor(包括它们自己)以执行复杂的操作序列。actor 之间的所有消息是异步的,这意味着发送者会在收到任何回复之前继续进行处理。因此,一个 actor 可能终生都陷入接收和处理消息的无限循环中。
当使用多个 actor 时,独立的活动可轻松分配到多个可并行执行消息的线程上(进而分配在多个处理器上)。一般而言,每个 actor 都在一个独立线程上处理消息。一些 actor 系统静态地向 actor 分配线程;而其他系统(比如本文中介绍的系统)则会动态地分配它们。
下面我们会分析下java中的一个actor模型框架的实现:
我们先看下elang中的actor模型的实现:
以Erlang为例子,介绍一下简单的Actor模型
1.首先建立一个Actor,在erlang中,起一个进程(这个是erlang虚拟机进程,跟os进程不同),这个进程就是actor了,可以用来接收和发送各种消息了
Pid = spawn(Mod,func,Args) %起一个进程
2.处理收到的消息
func()->
receive
{From,Msg}-> %收到一个消息
%%do something
func();
3.要对这个actor发送消息,也非常简单
Pid ! {From,Msg}
ujavaactor框架:
下面摘自ibm developer的一段介绍
μJavaActors 是 actor 系统的一个简单的 Java 实现。只有 1,200 行代码,μJavaActors 虽然很小,但很强大。在下面的练习中,您将学习如何使用 μJavaActors 动态地创建和管理 actor,将消息传送给它们。
μJavaActors 围绕 3 个核心界面而构建:
- 消息 是在 actor 之间发送的消息。
Message是 3 个(可选的)值和一些行为的容器:source是发送 actor。subject是定义消息含义的字符串(也称为命令)。data是消息的任何参数数据;通常是一个映射、列表或数组。参数可以是要处理和/或其他 actor 要与之交互的数据。subjectMatches()检查消息主题是否与字符串或正则表达式匹配。μJavaActors 包的默认消息类是DefaultMessage。- ActorManager 是一个 actor 管理器。它负责向 actor 分配线程(进而分配处理器)来处理消息。
ActorManager拥有以下关键行为或特征:createActor()创建一个 actor 并将它与此管理器相关联。startActor()启动一个 actor。detachActor()停止一个 actor 并将它与此管理器断开。send()/broadcast()将一条消息发送给一个 actor、一组 actor、一个类别中的任何 actor 或所有 actor。在大部分程序中,只有一个ActorManager,但如果您希望管理多个线程和/或 actor 池,也可以有多个ActorManager。此接口的默认实现是DefaultActorManager。- Actor 是一个执行单元,一次处理一条消息。
Actor具有以下关键行为或特征:- 每个 actor 有一个
name,该名称在每个ActorManager中必须是惟一的。 - 每个 actor 属于一个
category;类别是一种向一组 actor 中的一个成员发送消息的方式。一个 actor 一次只能属于一个类别。 - 只要
ActorManager可以提供一个执行 actor 的线程,系统就会调用receive()。为了保持最高效率,actor 应该迅速处理消息,而不要进入漫长的等待状态(比如等待人为输入)。 willReceive()允许 actor 过滤潜在的消息主题。peek()允许该 actor 和其他 actor 查看是否存在挂起的消息(或许是为了选择主题)。remove()允许该 actor 和其他 actor 删除或取消任何尚未处理的消息。getMessageCount()允许该 actor 和其他 actor 获取挂起的消息数量。getMaxMessageCount()允许 actor 限制支持的挂起消息数量;此方法可用于预防不受控制地发送。大部分程序都有许多 actor,这些 actor 常常具有不同的类型。actor 可在程序启动时创建或在程序执行时创建(和销毁)。本文中的 actor 包 包含一个名为AbstractActor的抽象类,actor 实现基于该类。12:59:38.883 T [main ] - TestActor activate: TestActor[name=common06, category=TestActor, messages=0]12:59:38.886 T [main ] - TestActor activate: TestActor[name=common05, category=TestActor, messages=0]12:59:38.887 T [main ] - TestActor activate: TestActor[name=common08, category=TestActor, messages=0]12:59:38.889 T [main ] - TestActor activate: TestActor[name=common07, category=TestActor, messages=0]12:59:38.890 T [main ] - TestActor activate: TestActor[name=common09, category=TestActor, messages=0]12:59:38.891 T [main ] - TestActor activate: TestActor[name=common00, category=TestActor, messages=0]12:59:38.892 T [main ] - TestActor activate: TestActor[name=common01, category=TestActor, messages=0]12:59:38.893 T [main ] - TestActor activate: TestActor[name=common02, category=TestActor, messages=0]12:59:38.895 T [main ] - TestActor activate: TestActor[name=common03, category=TestActor, messages=0]12:59:38.896 T [main ] - TestActor activate: TestActor[name=common04, category=TestActor, messages=0]12:59:38.897 T [main ] - TestActor activate: TestActor[name=actor24, category=default, messages=0]12:59:38.899 T [main ] - TestActor activate: TestActor[name=actor11, category=default, messages=0]12:59:38.904 T [main ] - TestActor activate: TestActor[name=actor23, category=default, messages=0]12:59:38.905 T [main ] - TestActor activate: TestActor[name=actor10, category=default, messages=0]12:59:38.906 T [main ] - TestActor activate: TestActor[name=actor22, category=default, messages=0]12:59:38.907 T [main ] - TestActor activate: TestActor[name=actor13, category=default, messages=0]12:59:38.908 T [main ] - TestActor activate: TestActor[name=actor21, category=default, messages=0]12:59:38.909 T [main ] - TestActor activate: TestActor[name=actor12, category=default, messages=0]12:59:38.910 T [main ] - TestActor activate: TestActor[name=actor20, category=default, messages=0]12:59:38.911 T [main ] - TestActor activate: TestActor[name=actor02, category=default, messages=0]12:59:38.912 T [main ] - TestActor activate: TestActor[name=actor01, category=default, messages=0]12:59:38.914 T [main ] - TestActor activate: TestActor[name=actor00, category=default, messages=0]12:59:38.915 T [main ] - TestActor activate: TestActor[name=actor19, category=default, messages=0]12:59:38.916 T [main ] - TestActor activate: TestActor[name=actor06, category=default, messages=0]12:59:38.917 T [main ] - TestActor activate: TestActor[name=actor18, category=default, messages=0]12:59:38.917 T [main ] - TestActor activate: TestActor[name=actor05, category=default, messages=0]12:59:38.918 T [main ] - TestActor activate: TestActor[name=actor04, category=default, messages=0]12:59:38.919 T [main ] - TestActor activate: TestActor[name=actor03, category=default, messages=0]12:59:38.920 T [main ] - TestActor activate: TestActor[name=actor15, category=default, messages=0]12:59:38.921 T [main ] - TestActor activate: TestActor[name=actor14, category=default, messages=0]12:59:38.922 T [main ] - TestActor activate: TestActor[name=actor09, category=default, messages=0]12:59:38.923 T [main ] - TestActor activate: TestActor[name=actor17, category=default, messages=0]12:59:38.923 T [main ] - TestActor activate: TestActor[name=actor08, category=default, messages=0]12:59:38.924 T [main ] - TestActor activate: TestActor[name=actor16, category=default, messages=0]12:59:38.925 T [main ] - TestActor activate: TestActor[name=actor07, category=default, messages=0]12:59:38.926 T [main ] - main waiting: 120...12:59:42.970 T [actor3 ] - TestActor:common06 init(4): TestActor[name=common06, category=TestActor, messages=0]12:59:43.028 T [actor2 ] - TestActor:common03 init(8): TestActor[name=common03, category=TestActor, messages=0]12:59:43.048 T [actor1 ] - TestActor:common01 init(6): TestActor[name=common01, category=TestActor, messages=0]12:59:43.054 T [actor8 ] - TestActor:common05 init(4): TestActor[name=common05, category=TestActor, messages=0]12:59:43.064 T [actor6 ] - TestActor:common09 init(8): TestActor[name=common09, category=TestActor, messages=0]12:59:43.873 T [actor0 ] - TestActor:common02 init(7): TestActor[name=common02, category=TestActor, messages=0]12:59:43.898 T [actor9 ] - TestActor:common08 init(1): TestActor[name=common08, category=TestActor, messages=0]12:59:43.993 T [actor7 ] - TestActor:common04 init(2): TestActor[name=common04, category=TestActor, messages=1]12:59:43.994 T [actor5 ] - TestActor:common00 init(1): TestActor[name=common00, category=TestActor, messages=0]12:59:43.996 W [actor2 ] - init:common03 to is null: actor512:59:44.039 W [actor8 ] - init:common05 to is null: actor912:59:44.052 W [actor1 ] - init:common01 to is null: actor912:59:44.060 T [actor4 ] - TestActor:common07 init(5): TestActor[name=common07, category=TestActor, messages=0]12:59:44.912 W [actor0 ] - init:common02 to is null: actor612:59:44.968 W [actor5 ] - init:common00 to is null: actor912:59:44.986 W [actor3 ] - init:common06 to is null: actor112:59:44.986 W [actor7 ] - init:common04 to is null: actor912:59:45.108 W [actor4 ] - init:common07 to is null: actor812:59:45.947 T [actor9 ] - TestActor:actor13 init(7): TestActor[name=actor13, category=default, messages=0]12:59:45.951 T [actor5 ] - TestActor:actor22 init(1): TestActor[name=actor22, category=default, messages=1]12:59:45.976 W [actor3 ] - init:common06 to is null: actor112:59:46.016 W [actor2 ] - init:common03 to is null: actor612:59:46.052 W [actor1 ] - init:common01 to is null: actor612:59:46.115 W [actor4 ] - init:common07 to is null: actor912:59:46.932 W [actor3 ] - init:common06 to is null: actor512:59:46.940 W [actor5 ] - init:actor22 to is null: actor312:59:47.039 T [actor7 ] - TestActor:actor24 init(8): TestActor[name=actor24, category=default, messages=1]12:59:47.042 W [actor1 ] - init:common01 to is null: actor612:59:47.059 W [actor2 ] - init:common03 to is null: actor012:59:47.904 T [actor8 ] - TestActor:actor21 init(7): TestActor[name=actor21, category=default, messages=1]12:59:47.964 T [actor3 ] - TestActor:actor10 init(4): TestActor[name=actor10, category=default, messages=0]12:59:47.988 T [actor5 ] - TestActor:actor23 init(7): TestActor[name=actor23, category=default, messages=2]12:59:48.003 W [actor6 ] - init:common09 to is null: actor312:59:48.042 W [actor1 ] - init:common01 to is null: actor612:59:48.072 W [actor2 ] - init:common03 to is null: actor812:59:48.101 W [actor4 ] - init:common07 to is null: actor612:59:48.880 W [actor8 ] - init:actor21 to is null: actor812:59:48.903 W [actor9 ] - init:actor13 to is null: actor312:59:48.952 T [main ] - main waiting: 110...12:59:49.024 W [actor2 ] - init:common03 to is null: actor312:59:49.037 W [actor6 ] - init:common09 to is null: actor912:59:49.085 W [actor4 ] - init:common07 to is null: actor6
源代码打包在附件中见http://zhwj184.iteye.com/admin/blogs/1613351
- 每个 actor 有一个