Akka 和 μJavaActors入门
Akka和μJavaActorsμJavaActors均是java的Actor库,其中Akka提供了叫为完整的Actor开发框架,较为庞大,学习成本很高,μJavaActors 是一个轻量级Actor库,大约仅有1200行代码,比较适合入门。
一.Akka Demo
Akka是一个相当成熟、强大的库,github上download下的是Akka的源码,应该使用sbt构建的工程,如果没有使用sbt经验,想导出jar还挺不容易的,推荐Akka官网下载akka各个组件的jar去使用,简单介绍一下helloworld 级别Akka的demo。
1.Akka的主要组件
akka-actor.jar : Actor核心组件了,定义了Acotr核心类
akka-slf4f.jar : SLF4F Logger的支持,一个打log的组件,不用太关注
akka-remote.jar : Actor做远程调用的jar,类似RFC吧
akka-cluster : actor做集群管理组件
akka-camel.jar : 对Apache Camel 集成接口
scala-library-2.11.8.jar : akka核心应该是Scala写的,这个组件就是对akka的核心支持
Akka还有很多组件,不过对于hello world级的程序简单了解几个就ok了。工程是基于eclipse的,需要包含下面几个基础的组件:

编写两个Actor:
package demo02; import akka.actor.UntypedActor;
/*
* UntypedAcotr是无类型Actor的一个抽象类,继承与核心类Actor
*/
public class Greeter extends UntypedActor { public static enum Msg{
GREET , DONE;
}
/**
* 每个Actor必须实现OnReceive,当该Actor收到消息调用该方法
*/
@Override
public void onReceive(Object msg) throws Throwable {
if(msg == Msg.GREET){
System.out.println("Hello world");
/**
* 这里吐槽一下Akka对于发消息的设计,发送消息的设计竟然是:
* receiver.tell(msg , sender)
* 也许没理解akka设计的理念,但是正常人设计不应该是:
* sender.tell(msg , receiver)
* 汗……
*/
getSender().tell(Msg.DONE, getSelf());
}else{
unhandled(msg);
} } }
package demo02; import akka.actor.ActorRef;
import akka.actor.Props;
import akka.actor.UntypedActor; public class HelloWorld extends UntypedActor { @Override
public void preStart(){
final ActorRef greeter = getContext().actorOf(Props.create(Greeter.class));
greeter.tell(Greeter.Msg.GREET, getSelf());
} @Override
public void onReceive(Object msg) throws Throwable { if(msg == Greeter.Msg.DONE){
getContext().stop(getSelf());
}else{
unhandled(msg);
} } }
下面是Main方法:
package demo02; import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.actor.Terminated;
import akka.actor.UntypedActor;
import akka.event.Logging;
import akka.event.LoggingAdapter; public class Main { public static void main(String[] args) {
//ActorSystem 相当于ActorManager,管理各种Acor调度、线程管理等
ActorSystem system = ActorSystem.create("hello");
//创建一个HelloWorld 类型的Actor,在Actor启动前,会调preStart(),此时会想Greeter发消息
ActorRef actor = system.actorOf(Props.create(HelloWorld.class));
//添加结束终结Actor,当ActorSystem调Stop时,会向每个Actor发送Terminated消息
system.actorOf(Props.create(Terminator.class, actor), "terminator"); }
public static class Terminator extends UntypedActor{ private final LoggingAdapter log = Logging.getLogger(getContext().system(),this);
private ActorRef actorRef = null; public Terminator(ActorRef ref){
System.out.println("Terminator Init !!!");
actorRef = ref;
getContext().watch(actorRef);
} @Override
public void onReceive(Object msg) throws Throwable {
if (msg instanceof Terminated) {
log.info("{} has terminated, shutting down system", actorRef.path());
getContext().system().terminate();
} else {
unhandled(msg);
} } } }
上面代码在akka的源码中sample都可以找到的,从上面看Akka对消息的识别是根据类型处理的,在我这种菜鸟看来,并不是很合适,当我消息类型较多时,消息类岂不是要爆炸,当然也可以做分级Actor,再加一层转发层解决这个问题哈
二.μJavaActors
μJavaActors 是一个十分轻量级的Actor库,实现核心的Actor调度,不涉及复杂的框架,简单分析一下它的源码吧
1.Actor核心接口
Actor:定义了一个标准的Actor应该具有行为
ActorManager:Actor管理器接口,提供线程管理,Actor调度等
Messager : Actor相互间传递传递的消息接口,当然附带的接口还有MessageEvent和MessageListener
简单引用作者对这个概念的描述:
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 实现基于该类。
ActorManager 是一个 actor 管理器。它负责向 actor 分配线程(进而分配处理器)来处理消息。ActorManager 拥有以下关键行为或特征:
createActor()创建一个 actor 并将它与此管理器相关联。startActor()启动一个 actor。detachActor()停止一个 actor 并将它与此管理器断开。send()/broadcast()将一条消息发送给一个 actor、一组 actor、一个类别中的任何 actor 或所有 actor。
在大部分程序中,只有一个 ActorManager,但如果您希望管理多个线程和/或 actor 池,也可以有多个 ActorManager。此接口的默认实现是 DefaultActorManager。
消息 是在 actor 之间发送的消息。Message 是 3 个(可选的)值和一些行为的容器:
source是发送 actor。subject是定义消息含义的字符串(也称为命令)。data是消息的任何参数数据;通常是一个映射、列表或数组。参数可以是要处理和/或其他 actor 要与之交互的数据。subjectMatches()检查消息主题是否与字符串或正则表达式匹配。
μJavaActors 包的默认消息类是 DefaultMessage。
ActorManager其实只要简单浏览一下μJavaActors源码就可以理解Actor设计思路啦,主要分析一下ActorManager中的Actor调度源码:
public class ActorRunnable implements Runnable {
public boolean hasThread;
public AbstractActor actor;
public void run() {
// logger.trace("procesNextActor starting");
int delay = 1;
while (running) {
try {
if (!procesNextActor()) {
// logger.trace("procesNextActor waiting on actor");
// sleep(delay * 1000);
synchronized (actors) {
// TOOD: adjust this delay; possible parameter
// we want to minizmize overhead (make bigger);
// but it has a big impact on message processing
// rate (makesmaller)
// actors.wait(delay * 1000);
actors.wait(100);
}
delay = Math.max(5, delay + 1);
} else {
delay = 1;
}
} catch (InterruptedException e) {
} catch (Exception e) {
logger.error("procesNextActor exception", e);
}
}
// logger.trace("procesNextActor ended");
}
protected boolean procesNextActor() {
boolean run = false, wait = false, res = false;
actor = null;
synchronized (actors) {
for (String key : runnables.keySet()) {
actor = runnables.remove(key);
break;
}
}
if (actor != null) {
// first run never started
run = true;
actor.setHasThread(true);
hasThread = true;
try {
actor.run();
} finally {
actor.setHasThread(false);
hasThread = false;
}
} else {
synchronized (actors) {
for (String key : waiters.keySet()) {
actor = waiters.remove(key);
break;
}
}
if (actor != null) {
// then waiting for responses
wait = true;
actor.setHasThread(true);
hasThread = true;
try {
res = actor.receive();
if (res) {
incDispatchCount();
}
} finally {
actor.setHasThread(false);
hasThread = false;
}
}
}
// if (!(!run && wait && !res) && a != null) {
// logger.trace("procesNextActor %b/%b/%b: %s", run, wait, res, a);
// }
return run || res;
}
}
ActorMgr中有一个线程队列维护了一些ActorRunnable对象,每个ActorRunnable对象有都在无线循环调度Actor,这也就简单使得每个Actor在不同的线程中执行。当然此时会有个问题,如果有一些Actor出现资源竞争会不会出现问题,答案肯定是会的。Actor仅仅是抽象了线程调度问题并给出了一下Actor的原则,并不能完全避免资源竞争现象的出现,只能说准守Actor模式规范,,当然也可以用redis去做公共内存块,避免直接的全局资源读写。
Akka 和 μJavaActors入门的更多相关文章
- Akka 简介与入门
Akka 简介与入门 http://www.thinksaas.cn/group/topic/344095/ 参考官网 http://akka.io/ 开源代码 https://github.co ...
- 分布式应用框架Akka快速入门
转自:http://blog.csdn.net/jmppok/article/details/17264495 本文结合网上一些资料,对他们进行整理,摘选和翻译而成,对Akka进行简要的说明.引用资料 ...
- Akka入门实例
Akka入门实例 Akka 是一个用 Scala 编写的库,用于简化编写容错的.高可伸缩性的 Java 和 Scala 的 Actor 模型应用. Actor模型并非什么新鲜事物,它由Carl Hew ...
- Scala进阶之路-并发编程模型Akka入门篇
Scala进阶之路-并发编程模型Akka入门篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Akka Actor介绍 1>.Akka介绍 写并发程序很难.程序员不得不处 ...
- 大数据入门第二十一天——scala入门(二)并发编程Akka
一.概述 1.什么是akka Akka基于Actor模型,提供了一个用于构建可扩展的(Scalable).弹性的(Resilient).快速响应的(Responsive)应用程序的平台. 更多入门的基 ...
- Akka入门
原文:http://doc.akka.io/docs/akka/2.3.6/intro/getting-started.html 预备知识 AKKA要求你的计算机已经安装了Java1.6或更高版本. ...
- akka 入门
http://blog.csdn.net/thkhxm/article/details/40182835 1.首先安装akka的相关包-- http://akka.io/downloads/2.导入依 ...
- Akka源码分析-Akka-Streams-概念入门
今天我们来讲解akka-streams,这应该算akka框架下实现的一个很高级的工具.之前在学习akka streams的时候,我是觉得云里雾里的,感觉非常复杂,而且又难学,不过随着对akka源码的深 ...
- Akka.NET v1.0 已发布,支持Mono
Akka.NET 是Java/Scala 流行框架Akka的一个 .NET 开源移植.可用于构建高并发,分布式和容错事件驱动的应用在 .NET 和 Mono 平台之上.Akka.NET 经过一年多的努 ...
随机推荐
- 求 1 到 n 的所有数的约数和
求 1 到 n 的所有数的约数和 暴力方法就是枚举每个数,算出他的约数和即可,这样有点慢. 另一种思路,枚举约数,判断他是谁的约数,并记录(即他的倍数有多少个),在乘以他自己. n/i求的是n以内,i ...
- python协程--yield和yield from
字典为动词“to yield”给出了两个释义:产出和让步.对于 Python 生成器中的 yield 来说,这两个含义都成立.yield item 这行代码会产出一个值,提供给 next(...) 的 ...
- js武器库
打造自己的 JavaScript 武器库 2017-12-14 SlaneYang JavaScript 自己打造一把趁手的武器,高效率完成前端业务代码. 前言 作为战斗在业务一线的前端,要想少加班, ...
- C# 引用访问权限
同样代码表现的不同行为 创建基类(Super)和派生类(Sub)每个类有一个字段field和一个公共方法getField,并且使用内联的方式初始化为1,方法getField返回字段field.C#和J ...
- IOS笔记046-UIApplication/导航控制器
UIApplication 每一个应用都有自己的UIApplication对象,而且是单例的 通过[UIApplication sharedApplication]可以获得这个单例对象 一个iOS程序 ...
- 链表的问题,ListNode问题
算法面试,有关ListNode的问题 class ListNode{ ListNode *next; int val; ListNode(int x): val(x){}}; 在面试的时候,怎么快速想 ...
- jquery对象与js对象
对于已经是一个 DOM 对象,只需要用 $() 把DOM对象包装起来,就可以获得一个 jQuery 对象了,使用[index]和.get(index)可以转为DOM对象 jQuery 对象是通过 jQ ...
- BZOJ 1787: [Ahoi2008]Meet 紧急集合(lca+贪心)
[Ahoi2008]Meet 紧急集合 Description Input Output Sample Input 6 4 1 2 2 3 2 4 4 5 5 6 4 5 6 6 3 1 2 4 4 ...
- 【bzoj2431】[HAOI2009]逆序对数列 dp
题目描述 对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数.若对于任意一个由1~n自然数组成的 数列,可以很容易求出有多少个逆序对数.那么逆序对数为k的这 ...
- NBUT 1618 投放炸弹(树状数组)
[1618] 投放炸弹 时间限制: 1000 ms 内存限制: 65535 K 问题描述 我们定义一个炸弹能炸毁的地方要求曼哈顿距离小于等于某个值. 曼哈顿距离——两点在南北方向上的距离加上在东西方向 ...