erlang学习笔记
Contents
erlang 之简单的Diction实现
最近在看学erlang ,看到了字典这个demo ,把程序Copy出来和大家分享一下
|
|
函数编程习惯之后,写起来也是挺爽的意见事,基本上都是递归的思想。
erlang 之简单密码加密
这些程序主要是来之 连城 翻译的一个书里面的代码
|
|
erlang 简单的树操作
|
|
代码不多,erlang写算法……呵呵呵呵呵呵
erlang 并发编程
最近上班比较忙,没时间学习erlang ,实在对不起自己啊,以前一直在找erlang相关的教程,终于找到一个了,这个网站是前几天才开始运行的,以后的文章可能都是来自于那里,网站是http://www.erlang-cn.com ,大家忙没事多学习!大笑
- 并发编程一
|
|
进程的标识 ,我们还有一种更加灵活的方法来标记她那就是使用register函数
|
|
register中的pong就标识了spawn(tut16,pong,[])这个进程,这个ping()函数只要一个N就行了,pong可以看作是进程之间共享的变量.
erlang 之 echo 服务器
简单实现了一个echo 服务器
- echo_server1
|
|
Output:
|
|
其中 stop 是主进程的返回值
- echo_server2
这是一个简单用于等待外部信息的echo server
|
|
timeout 的简单使用
今天晚上有点晚了,不过还是坚持每一天写一个程序!
下面的时超时器 :
建设A要想db进程发送一个信息,然后在规定的时间内等待消息的返回,那么A可以设置一个超时器,注意的是在发送消息之前,得先清空消息队列,要不然等译接到的消息可能db还没发送之前的了.
|
|
Erlang进程生成测试
|
|
进程退出时会返回ok。
erlang之时钟
今天来看一下erlang中的时钟如何实现的:
|
|
上面主要是睡眠 和清空“邮箱” ,还有就是优先级的简单实现.
下面再来一段吧:
|
|
shell中演示一下:
|
|
a simple erlang process pool analysis

这是一个简单的erlang进程池分析,是learn you some erlang for Great Good里面的一个example,详细的内容可到官网查看!
- 实现原理
这个的例子的实现原理官网都有比较详细的说明,主要模块在ppool_serv中,ppool_serv是一个gen_server behaviour, 而ppool_sup是一个one_for_all的策略,如果ppool_serv或者worker_sup出现问题,彼此也没有存在的必要了。
这里ppool_serv和worker_sup的实现,使用了一个简单的技巧,因为worker_sup不是ppool_sup直接调用生成的,它是由ppool_serv控制生成的:
|
|
woker_sup由ppool_serv自己在init函数中,发给自己一个Message,然后在回调函数中才生成:
|
|
如果他们一起直接生产,那么会产生死锁,

当然,他这里的生成顺序,可以自己修改一下,也不会出现死锁。
gen_serv的主要数据结构
|
|
?SPEC(MFA), 这里的MFA指明一类Task,所以同一个ppool_worker_sup,不会有不同类型的Task,它的策略也是simple_one_for_one.
在这个例子中,使用了一个gen_server -- nnager module作为Task,这个Task的参数为:{Task, Delay, Max, SendTo}, Task标示任务名字,Delay作为超时时间,只是标示这个任务是有超时限制的,也是一个调试技巧,Max为最大超时次数,SendTo用来发送信息给回调进程,这个进程可以是shell, 如果是shell,flush()就会收到信息。
record用来标识一些主要的信息,Limit为进程池的大小限制,sup开始为ppool_sup的pid(),在生成woker_sup进程后,就变成worker_sup的进程pid(),因为ppool_serv的主要交流对象还是worker_sup和worker(Task); refs(gb_set)为woker的进程链接,这样可以在worker进程down掉或者done时,从线程池中剔除掉;queue为任务队列,当任务大于limit时,就把多余的任务放到queque中,等到进程池有空闲时,就从中pop出任务,接着处理。
这里有些局限的地方:
- 每次的任务都是新建的进程去处理,就是说进程的生命周期跟任务的生命周期是一样的,可以把进程跟任务分离出来,让进程不随任务的结束而结束(当然这的任务就不要是gen_server,gen_fsm这些,因为这些也是spawn出来的进程),这样进程开销理论上一次初始化就行了,虽然进程在erlang中开销比较少;
- 队列没有大小限制
PoolBoy
source code :
https://github.com/devinus/poolboy

- Checkout
|
|
Checkout出一个worker从worker Queue中,如果有,则monitor(ets)这个worker,然后根据队列的容量和MaxOverflow的值来确定下一状态为full,overflow,ready (ready + overflow <= full);如果没有,而MaxOverFlow的值大于0,则新建一个worker,并将其加入monitor,最后重置状态项worker = empty, overflow = 1;如果没有,并且MaxOverflow 小于1, Block == false,则{reply, full, full, State#state{workers=Empty}};如过没有,MaxOverflow < 1, Block == true,则 {next_state, full, State#state{workers=Empty, waiting=Waiting}}。
- Checkin
|
|
从Monitor中剔除对应的worker,然后回收到worker queue中去。
状态转变
- 状态转变的计算:
worker_queue_size(当前size) + maxoverflow 。
ready只与当前worker_queque_size有关,overflow 和worker_queue_size(0)和maxoverflow>0有关,full和work_queue_size(0), overfllow = maxoverflow有关。
- worker的来源
所有的worker要么在初始化时创建平;要么调用checkout时,经过poolboy创建,但此时创建的worker没有进到worker queue,要想进到worker queue,只能调用checkin。
work pid 回收到worker_queue中
|
|