- 浏览: 129556 次
- 性别:
- 来自: 杭州
最新评论
-
zhi_nan_7:
做一个软件,需求是这样的:银行软件,需要对(excel)表格 ...
如何应对表结构经常变化? -
GuolinLee:
{A, _int, [B|_int], {B}} = {abc ...
erlang 中带下划线变量的使用 -
mozhenghua:
兄弟有没有啥解决方案呀?
MVC中被忽略的View层 -
ccchenzhong:
仁兄,还有哪边有你的这篇文章可看。如果有,可以给我个链接?或是 ...
javarebel 原理分析--说明 -
lingqi1818:
一晃一年过去了。。。
回顾2010,展望2011
好戏开始了
Erlang 的程序由很多process组成,这些process和人很象:
• 都有自己的一份memory,并且不会互相影响
• 如果要影响别人的memory,都必须明确告诉对方,比如发个消息(说句话)啥的
• 当然,说了别人不一定听,还得确认一下,哥们,明白了么?
• 这些process如果挂了,会在最后吼出来:考,老子被零除!啊!
• 这样,其他的process就会知道,哦,谁谁谁挂了。
• 还有,process间还可以达成某总协议,比如说,一方挂了,另一方帮忙处理后事,之类的。
• 归纳一下就是:
• 1. Erlang程序是由很多进程组成,这些进程之间可以互相发消息。(这个进程和传统意义上操作系统里的进程是不一样的,只是概念上差不多)
• 2. 这些消息不一定能收到或者明白,如果要确认这一点的话,必须发送消息之后等回答
• 3. 两个进程可以结对,连接在一起,如果其中一方挂了,另一方会得到死因
Think of people in a room. The people are the processes. The people in the room have individual private memories; this is the state of a process. To change your memory, I talk to you, and you listen. This is sending and receiving messages. We have children; this is spawn. We die; this is a process exit.
这就是Erlang的模型。
和操作系统的进程相比,Erlang的进程
• 创建和销毁都很快
• 进程间发送消息很快
• 在所有操作系统上,这些进程都一样的工作
• 可以有非常大数量的进程,例如几十万,几百万?
• 进程之间没有共享内存,完全互相独立
• 进程间唯一的交互途径就是发送消息
The Concurrency Primitives
• 1. Pid = spawn(Fun).
• 或者 spawn(Module,Fun,Args). 推荐这种方式,动态更新代码有用
• 创建一个和调用者并行的新进程来执行Fun,可以通过返回的Pid来发送消息
• 2. Pid!Message
• 发送一条消息给Pid对应的进程,该语句返回Message本身,因此Pid1!Pid2!Pid3..!Message,就可以将Message发给所有这些进程
• 发送消息的过程是异步的
• 3. receive ... end
receive
Pattern1 [when Guard1] ->
Expressions1;
Pattern2 [when Guard2] ->
Expressions2;
...
end
• 当进程收到消息的时候,挨个匹配这些Pattern,如果匹配到就执行,否则匹配下一条,都没匹配到的话,就把消息保存起来
一个简单的例子
-module(area_server0).
-export([loop/0]).
loop() ->
receive
{rectangle, Width, Ht} ->
io:format("Area of rectangle is ~p~n" ,[Width * Ht]),
loop();
{circle, R} ->
io:format("Area of circle is ~p~n" , [3.14159 * R * R]),
loop();
Other ->
io:format("I don't know what the area of a ~p is ~n" ,[Other]),
loop()
end.
• 首先,在shell里起来 Pid = spawn(fun area_server0:loop/0).
• 然后就可以使用了 Pid ! {rectangle, 6, 10}.
Client-Server 结构
• Erlang里大量使用到C/S结构
• 这里的client和server都是erlang里的进程,都很轻量
• 可以在同一台机器也可以分布在不同的机器上
• 是按其职责来区分client和server的,client发送请求给server,然后server处理之后返回
• 和写信一样,要收到回信就要送过去自己的地址,要收到回答的消息,就必须告诉对方自己的地址(Pid)
-module(area_server_final).
-export([start/0, area/2]).
start() -> spawn(fun loop/0). %% 启动
area(Pid, What) ->
rpc(Pid, What).
rpc(Pid, Request) ->
Pid ! {self(), Request}, %% 发送消息给server
receive
{Pid, Response} -> %% 接收server发回的消息,通过Pid来确认
Response
end.
loop() ->
receive
{From, {rectangle, Width, Ht}} ->
From ! {self(), Width * Ht}, %% 返回结果,并加上自己的身份self(),以确认确实是自己返回的
loop();
{From, {circle, R}} ->
From ! {self(), 3.14159 * R * R},
loop();
{From, Other} ->
From ! {self(), {error,Other}},
loop()
end.
erlang 创建进程有多快?
• Erlang的进程数限制,通过erlang:system_info(process_limit)可以得到,一般是32768(32位机器),要调整可以通过命令行
• erl +P 1000000 来设置
• erlang 创建进程非常快,非常非常快,可以自己试试看
• 在我的笔记本上得到的结果,看起来跑个60万没问题的,当然是什么活都没干,呵呵
8> processes:max(500000).
Maximum allowed processes:1000000
Process spawn time=4.32 (6.858) microseconds
ok
9> processes:max(600000).
Maximum allowed processes:1000000
Process spawn time=4.316666666666666 (6.801666666666667) microseconds
ok
10> processes:max(700000).
Maximum allowed processes:1000000
Process spawn time=4.571428571428571 (7.062857142857143) microseconds
• 使用的程序如下:
-module(processes).
-export([max/1]).
%% max(N)
%% Create N processes then destroy them
%% See how much time this takes
max(N) ->
Max = erlang:system_info(process_limit),
io:format("Maximum allowed processes:~p~n" ,[Max]),
statistics(runtime),
statistics(wall_clock),
L = for(1, N, fun() -> spawn(fun() -> wait() end) end),
{_, Time1} = statistics(runtime),
{_, Time2} = statistics(wall_clock),
lists:foreach(fun(Pid) -> Pid ! die end, L),
U1 = Time1 * 1000 / N,
U2 = Time2 * 1000 / N,
io:format("Process spawn time=~p (~p) microseconds~n" ,
[U1, U2]).
wait() ->
receive
die -> void
end.
for(N, N, F) -> [F()];
for(I, N, F) -> [F()|for(I+1, N, F)].
接收消息时的超时
receive
Pattern1 [when Guard1] ->
Expressions1;
Pattern2 [when Guard2] ->
Expressions2;
...
after Time -> %% 超时时间,单位millisecond
Expressions
end
• receive 是在等待,因此我们可以轻松实现一个sleep
sleep(T) ->
receive
after T ->
true
end.
• 如果超时时间设置为0,表示马上超时,立即执行,但在此之前仍然会执行前面的pattern match
• 如果超时时间为infinity,表示永远不超时
• 利用receive ... after 可以轻易实现一个timer
-module(stimer).
-export([start/2, cancel/1]).
start(Time, Fun) -> spawn(fun() -> timer(Time, Fun) end).
cancel(Pid) -> Pid ! cancel.
timer(Time, Fun) ->
receive
cancel ->
void
after Time ->
Fun()
end.
接收消息
• 实际上,所有的发送给一个进程的消息都是保存在这个进程的邮箱里,当进程做receive的时候,就从邮箱里去取一条消息
• receive的实际工作过程是这样的
• 1. 执行receive的时候,启动一个timer(当然是设置了time out时间的情况下)
• 2. 从邮箱里取出第一条消息,进行匹配,如果匹配到某个规则,就从邮箱里删除这条消息,然后执行相应的代码
• 3. 如果没有匹配到任何一个pattern,就把消息移动到一个“保存队列”中,然后在取第二条,以此反复
• 4. 如果一条都没匹配上,进程就挂起等待新的消息进来,新消息进来的时候,只会那新到的消息去匹配,在“保存队列”里的消息不会再匹配过
• 5. 一旦有消息成功匹配,将“保存队列”里的消息按原来到达的次序放到邮箱里,清理timer
• 6. 如果在等待消息的过程中,timer到期了,将执行after 下的语句,同时把“保存队列”里的消息按原来顺序放回邮箱
Registered Processes
• 在erlang里,不知道进程的Pid就无法和他通信
• 但是有时需要让别的进程都和自己通信,这时可以使用registered process,实际上就是给自己起个名字,大家都用这个名字来通信
• register(AnAtom, Pid) 如果这个名字已经被注册了,注册将会失败
• unregister(AnAtom) 如果一个进程挂了,将会自动被取消注册
• whereis(AnAtom) -> Pid | undefined
• registered() -> [AnAtom::atom()]
• 例子,实现一个时钟
-module(clock).
-export([start/2, stop/0]).
start(Time, Fun) ->
register(clock, spawn(fun() -> tick(Time, Fun) end)).
stop() -> clock ! stop.
tick(Time, Fun) ->
receive
stop ->
void
after Time ->
Fun(),
tick(Time, Fun)
end.
32> clock:start(1000,fun() -> io:format("Time is ~p~n",[erlang:now()] ) end).
true
Time is {1221,716569,346481}
Time is {1221,716570,350670}
Time is {1221,716571,355489}
Time is {1221,716572,358767}
Time is {1221,716573,362840}
33> clock:stop().
stop
Erlang 的程序由很多process组成,这些process和人很象:
• 都有自己的一份memory,并且不会互相影响
• 如果要影响别人的memory,都必须明确告诉对方,比如发个消息(说句话)啥的
• 当然,说了别人不一定听,还得确认一下,哥们,明白了么?
• 这些process如果挂了,会在最后吼出来:考,老子被零除!啊!
• 这样,其他的process就会知道,哦,谁谁谁挂了。
• 还有,process间还可以达成某总协议,比如说,一方挂了,另一方帮忙处理后事,之类的。
• 归纳一下就是:
• 1. Erlang程序是由很多进程组成,这些进程之间可以互相发消息。(这个进程和传统意义上操作系统里的进程是不一样的,只是概念上差不多)
• 2. 这些消息不一定能收到或者明白,如果要确认这一点的话,必须发送消息之后等回答
• 3. 两个进程可以结对,连接在一起,如果其中一方挂了,另一方会得到死因
Think of people in a room. The people are the processes. The people in the room have individual private memories; this is the state of a process. To change your memory, I talk to you, and you listen. This is sending and receiving messages. We have children; this is spawn. We die; this is a process exit.
这就是Erlang的模型。
和操作系统的进程相比,Erlang的进程
• 创建和销毁都很快
• 进程间发送消息很快
• 在所有操作系统上,这些进程都一样的工作
• 可以有非常大数量的进程,例如几十万,几百万?
• 进程之间没有共享内存,完全互相独立
• 进程间唯一的交互途径就是发送消息
The Concurrency Primitives
• 1. Pid = spawn(Fun).
• 或者 spawn(Module,Fun,Args). 推荐这种方式,动态更新代码有用
• 创建一个和调用者并行的新进程来执行Fun,可以通过返回的Pid来发送消息
• 2. Pid!Message
• 发送一条消息给Pid对应的进程,该语句返回Message本身,因此Pid1!Pid2!Pid3..!Message,就可以将Message发给所有这些进程
• 发送消息的过程是异步的
• 3. receive ... end
receive
Pattern1 [when Guard1] ->
Expressions1;
Pattern2 [when Guard2] ->
Expressions2;
...
end
• 当进程收到消息的时候,挨个匹配这些Pattern,如果匹配到就执行,否则匹配下一条,都没匹配到的话,就把消息保存起来
一个简单的例子
-module(area_server0).
-export([loop/0]).
loop() ->
receive
{rectangle, Width, Ht} ->
io:format("Area of rectangle is ~p~n" ,[Width * Ht]),
loop();
{circle, R} ->
io:format("Area of circle is ~p~n" , [3.14159 * R * R]),
loop();
Other ->
io:format("I don't know what the area of a ~p is ~n" ,[Other]),
loop()
end.
• 首先,在shell里起来 Pid = spawn(fun area_server0:loop/0).
• 然后就可以使用了 Pid ! {rectangle, 6, 10}.
Client-Server 结构
• Erlang里大量使用到C/S结构
• 这里的client和server都是erlang里的进程,都很轻量
• 可以在同一台机器也可以分布在不同的机器上
• 是按其职责来区分client和server的,client发送请求给server,然后server处理之后返回
• 和写信一样,要收到回信就要送过去自己的地址,要收到回答的消息,就必须告诉对方自己的地址(Pid)
-module(area_server_final).
-export([start/0, area/2]).
start() -> spawn(fun loop/0). %% 启动
area(Pid, What) ->
rpc(Pid, What).
rpc(Pid, Request) ->
Pid ! {self(), Request}, %% 发送消息给server
receive
{Pid, Response} -> %% 接收server发回的消息,通过Pid来确认
Response
end.
loop() ->
receive
{From, {rectangle, Width, Ht}} ->
From ! {self(), Width * Ht}, %% 返回结果,并加上自己的身份self(),以确认确实是自己返回的
loop();
{From, {circle, R}} ->
From ! {self(), 3.14159 * R * R},
loop();
{From, Other} ->
From ! {self(), {error,Other}},
loop()
end.
erlang 创建进程有多快?
• Erlang的进程数限制,通过erlang:system_info(process_limit)可以得到,一般是32768(32位机器),要调整可以通过命令行
• erl +P 1000000 来设置
• erlang 创建进程非常快,非常非常快,可以自己试试看
• 在我的笔记本上得到的结果,看起来跑个60万没问题的,当然是什么活都没干,呵呵
8> processes:max(500000).
Maximum allowed processes:1000000
Process spawn time=4.32 (6.858) microseconds
ok
9> processes:max(600000).
Maximum allowed processes:1000000
Process spawn time=4.316666666666666 (6.801666666666667) microseconds
ok
10> processes:max(700000).
Maximum allowed processes:1000000
Process spawn time=4.571428571428571 (7.062857142857143) microseconds
• 使用的程序如下:
-module(processes).
-export([max/1]).
%% max(N)
%% Create N processes then destroy them
%% See how much time this takes
max(N) ->
Max = erlang:system_info(process_limit),
io:format("Maximum allowed processes:~p~n" ,[Max]),
statistics(runtime),
statistics(wall_clock),
L = for(1, N, fun() -> spawn(fun() -> wait() end) end),
{_, Time1} = statistics(runtime),
{_, Time2} = statistics(wall_clock),
lists:foreach(fun(Pid) -> Pid ! die end, L),
U1 = Time1 * 1000 / N,
U2 = Time2 * 1000 / N,
io:format("Process spawn time=~p (~p) microseconds~n" ,
[U1, U2]).
wait() ->
receive
die -> void
end.
for(N, N, F) -> [F()];
for(I, N, F) -> [F()|for(I+1, N, F)].
接收消息时的超时
receive
Pattern1 [when Guard1] ->
Expressions1;
Pattern2 [when Guard2] ->
Expressions2;
...
after Time -> %% 超时时间,单位millisecond
Expressions
end
• receive 是在等待,因此我们可以轻松实现一个sleep
sleep(T) ->
receive
after T ->
true
end.
• 如果超时时间设置为0,表示马上超时,立即执行,但在此之前仍然会执行前面的pattern match
• 如果超时时间为infinity,表示永远不超时
• 利用receive ... after 可以轻易实现一个timer
-module(stimer).
-export([start/2, cancel/1]).
start(Time, Fun) -> spawn(fun() -> timer(Time, Fun) end).
cancel(Pid) -> Pid ! cancel.
timer(Time, Fun) ->
receive
cancel ->
void
after Time ->
Fun()
end.
接收消息
• 实际上,所有的发送给一个进程的消息都是保存在这个进程的邮箱里,当进程做receive的时候,就从邮箱里去取一条消息
• receive的实际工作过程是这样的
• 1. 执行receive的时候,启动一个timer(当然是设置了time out时间的情况下)
• 2. 从邮箱里取出第一条消息,进行匹配,如果匹配到某个规则,就从邮箱里删除这条消息,然后执行相应的代码
• 3. 如果没有匹配到任何一个pattern,就把消息移动到一个“保存队列”中,然后在取第二条,以此反复
• 4. 如果一条都没匹配上,进程就挂起等待新的消息进来,新消息进来的时候,只会那新到的消息去匹配,在“保存队列”里的消息不会再匹配过
• 5. 一旦有消息成功匹配,将“保存队列”里的消息按原来到达的次序放到邮箱里,清理timer
• 6. 如果在等待消息的过程中,timer到期了,将执行after 下的语句,同时把“保存队列”里的消息按原来顺序放回邮箱
Registered Processes
• 在erlang里,不知道进程的Pid就无法和他通信
• 但是有时需要让别的进程都和自己通信,这时可以使用registered process,实际上就是给自己起个名字,大家都用这个名字来通信
• register(AnAtom, Pid) 如果这个名字已经被注册了,注册将会失败
• unregister(AnAtom) 如果一个进程挂了,将会自动被取消注册
• whereis(AnAtom) -> Pid | undefined
• registered() -> [AnAtom::atom()]
• 例子,实现一个时钟
-module(clock).
-export([start/2, stop/0]).
start(Time, Fun) ->
register(clock, spawn(fun() -> tick(Time, Fun) end)).
stop() -> clock ! stop.
tick(Time, Fun) ->
receive
stop ->
void
after Time ->
Fun(),
tick(Time, Fun)
end.
32> clock:start(1000,fun() -> io:format("Time is ~p~n",[erlang:now()] ) end).
true
Time is {1221,716569,346481}
Time is {1221,716570,350670}
Time is {1221,716571,355489}
Time is {1221,716572,358767}
Time is {1221,716573,362840}
33> clock:stop().
stop
发表评论
-
读了一下hotwheels的代码
2009-08-31 11:56 2561上次提到的一个挑战, ... -
不错的erlang tutorial
2009-08-19 09:41 1213http://learnyousomeerlang.com/ ... -
erlang 新书 "OTP and Erlang in Action"
2009-08-17 17:40 1374一本新书,似乎还未完成,见 http://pokingarou ... -
erlang.org似乎挂了
2009-08-17 11:38 1230从昨天起,erlang.org就无法访问了,ping能ping ... -
为啥我的erlide超慢无比?
2009-08-06 16:08 1376为啥我的erlide超慢无比? 刚下载的一个eclip ... -
erlang 程序性能优化挑战
2009-07-20 12:03 1964OpenPoker 的作者Joel Reymont 发起的 ... -
erlang programming 比programming erlang这本书好
2009-07-15 16:38 1911这两本书我都是看英文pdf的,看了TheBook之后,没啥感觉 ... -
erlang中的message发送的几个事实
2009-07-13 17:59 1834这个世界是并行的,我们每个人都有自己的思想,你没法知道我想什么 ... -
在ubuntu上编译erlang with wx
2009-07-12 09:10 1966因为ubuntu维护的erlang版本太旧,因此从某时开始,我 ... -
并不是所有的时候都应该选择尾递归
2009-07-08 17:06 1012要实现一个函数,参数是一个list,结果是将list里每个数字 ... -
erlang 中case语句的使用
2009-07-07 13:16 5952在erlang中,至少有三种可互换的流程控制方式:函数声明上的 ... -
erlang 中带下划线变量的使用
2009-07-03 15:39 3620在erlang里'_'是一个特殊的变量(其实erlang里不应 ... -
Erlang 基础学习 1
2008-09-16 02:55 1022Erlang Day 1 基础• 容错,在多核CPU上性能好, ... -
Erlang 基础学习 2 简单的程序
2008-09-16 07:49 1075Erlang Sequential ProgrammingMo ... -
Erlang 基础学习 3 异常处理
2008-09-17 08:09 1403Erlang Day 3 异常处理• 三种方式可以抛出异常• ... -
Erlang 基础学习 4 Advanced Sequential Programming
2008-09-17 08:11 1512Day 4 Advanced Sequential Progr ... -
Erlang 基础学习 5 编译和运行
2008-09-17 09:40 1818如何退出erlang 的shell• ... -
Erlang 基础学习 7 Errors in Concurrent Programs
2008-09-19 03:48 1911Linking Processes• 进程可以调用link(P ... -
Erlang 基础学习 8 Distributed programming
2008-09-25 06:22 1495Distributed Programming为啥需要分布式的 ... -
Erlang 基础学习 9 Interfacing Techniques
2008-09-26 02:39 1158• Erlang和外部程序的交互通过一种叫port的技术来通信 ...
相关推荐
**并发编程在Erlang中的应用(Concurrent Programming in ERLANG)** 本标题及描述明确指出了文档的主要内容是关于如何在Erlang语言中进行并发编程。Erlang是一种通用、并发、强类型、垃圾回收的编程语言,特别适用...
- 通过学习顺序编程的基础,读者可以更好地理解Erlang如何处理数据流和控制结构。 **1.2 数据类型** - Erlang中有多种基本数据类型,如整数、浮点数、原子等。 - 这些类型为构建复杂的数据结构提供了基础。 **1.3 ...
Joe的那篇erlang论文 Programming Erlang + 源码包 Erlang Programming Concurrent Programming in Erlang efficiecy guide 资源齐全.希望能帮到你.
《Concepts and Notations for Concurrent Programming》这篇论文由Gregory R. Andrews和Fred B. Schneider撰写,深入探讨了并行编程的核心概念和技术。尽管这是一篇较为古老的文章,但其内容仍然具有很高的参考价值...
Concurrent Programming in ERLANG可能深入讲解如何设计和管理并发进程,以及如何处理进程间的同步和异步通信。 3. **分布式系统**:“面对软件错误构建可靠的分布式系统.pdf”强调了Erlang在构建分布式系统时的...
Programming Erlang + 源码包 Erlang Programming Concurrent Programming in Erlang Joe的那篇erlang论文 efficiecy guide
Pragmatic Programmer,Pragmatic Programming,Pragmatic Bookshelf and the linking g device are trademarks of The Pragmatic Programmers,LLC. Every precaution was taken in the preparation of this book....
论文以实际案例为基础,重点介绍了一种并发函数式编程语言——Erlang。Erlang由爱立信公司的计算机科学实验室研发,并已作为开源软件提供给公众使用。目前,Erlang已在大约20个系统中得到应用,其中包括著名的ATM...
Erlang and OTP in Action teaches you to apply Erlang’s message passing model for concurrent programming–a completely different way of tackling the problem of parallel programming from the more ...
3. **书籍资料**:如《Programming Erlang: Software for a Concurrent World》是一本非常好的入门书籍。 通过以上介绍,我们不仅了解了Erlang的基础概念及其优势,还学习了如何安装配置Erlang环境以及简单的Erlang...
"Programming Erlang: Software for a Concurrent World"是Joe Armstrong编写的经典书籍,深入探讨了Erlang的设计哲学和技术细节。 在Erlang中,并发是核心特性之一。通过轻量级进程(Lightweight Processes, LWP)...
### 编程Erlang:面向并发世界的软件开发 #### 核心概念解析 **编程Erlang**这本书深入探讨了如何使用Erlang语言来编写高效、...对于那些希望在并发领域有所作为的开发者来说,学习Erlang绝对是一项值得投资的技能。
As a developer, you’ve probably heard that functional programming techniques help manage the complexities of today’s real-world, concurrent systems. You’re also investigating designs that help you ...
- **书籍推荐**:《Programming Erlang: Software for a Concurrent World》是一本很好的入门指南,由Erlang之父Joe Armstrong撰写,详细介绍了Erlang的基本概念和编程技巧。 - **在线课程**:许多在线教育平台提供...
《Programming Erlang: Software for a Concurrent World》是一本非常好的入门书籍,它不仅介绍了Erlang的基本概念,还提供了丰富的实例和实践指导。此外,还可以参考官方文档和其他在线教程,积极参与社区交流,以...