Erlang的进程是轻量级的,它的生成,上下文切换和消息传递都是虚拟机来管理的。操作系统线程和Erlang进程没有任何关系,独立于操作系统底层。Erlang中每一个处理器或者核心处理一个操作系统线程,而Java每一个进程代表一个操作系统线程。
进程传递消息,从发送进程堆复制到接受进程堆,避免了共享存储位置,每个进程都有副本。
一,注意点:
1.创建进程第三个参数是列表,这一点容易忽略
spawn(module,function,[args]).
2.内置函数processes()返回系统中所有运行者的进程列表
Eshell V10.5 (abort with ^G)
1> processes().
[<0.0.0>,<0.1.0>,<0.2.0>,<0.3.0>,<0.4.0>,<0.5.0>,<0.6.0>,
<0.9.0>,<0.41.0>,<0.43.0>,<0.45.0>,<0.46.0>,<0.48.0>,
<0.49.0>,<0.50.0>,<0.51.0>,<0.52.0>,<0.53.0>,<0.54.0>,
<0.55.0>,<0.56.0>,<0.57.0>,<0.58.0>,<0.59.0>,<0.60.0>,
<0.62.0>,<0.63.0>,<0.64.0>,<0.65.0>|...]
3.i()返回所有进程详细信息
1> i().
Pid Initial Call Heap Reds Msgs
Registered Current Function Stack
<0.0.0> erl_init:start/2 376 1676 0
init init:loop/1 2
<0.1.0> erts_code_purger:start/0 233 8 0
erts_code_purger erts_code_purger:wait_for_request 1
<0.2.0> erts_literal_area_collector:start 233 7 0
erts_literal_area_collector:msg_l 5
<0.3.0> erts_dirty_process_signal_handler 233 35 0
erts_dirty_process_signal_handler 2
<0.4.0> erts_dirty_process_signal_handler 233 7 0
erts_dirty_process_signal_handler 2
<0.5.0> erts_dirty_process_signal_handler 233 7 0
erts_dirty_process_signal_handler 2
4.process_flag(priority,P)可以设置进程优先级high,normal,low
9> self().
<0.76.0>
10> process_flag(priority,high).
normal
11> process_flag(priority,low).
high
12> process_flag(priority,normal).
low
二.消息传递
消息传递是Erlang的杀手级特性,以此实现进程通信,采用Pid!Msg来传递。需要注意一下几点
a.每个Erlang进程都有用来存储传入的信息的邮箱
b.消息按照传递的时间次序存储在邮箱里
c.发送消息永远不会失败,消息只会被丢弃,不会产生错误
d.消息传递是异步的,也就是不会等待返回结果回传而暂停运行
e.当一个消息不和receive中匹配的时候,会积累在邮箱,最后内存泄漏,最好忽略
self()代表当前进程,flush()会显示所有发送并且保存在终端的消息,同时被删除信箱的消息。
接收消息:
Erlang的信息是可以选择接受的
receive
{one,Msg}->Msg;
_Other->{error,unknow_msg}
end
Echo实例
go()->
Pid=spawn(?MODULE,loop,[]),
Pid!{self(),hello},
receive
{Pid,Msg}->
io:format("~w~n",[Msg])
end,
Pid!stop.
loop()->
receive
{From,Msg}->
From!{self(),Msg},
loop();
stop->
true
end.
三,注册进程
register(Alice,Pid)可以把具体的进程标志数字换成名字,直接调用名字即可。
go()->
register(alice,spawn(?MODULE,loop,[])),
alice!{self(),hello},
receive
{Pid,Msg}->
io:format("~w~n",[Msg])
end,
Pid!stop.
loop()->
receive
{From,Msg}->
From!{self(),Msg},
loop();
stop->
true
end.
whereis()可以知晓注册进程在那个地址。
regs()会显示所有注册的进程。
四,超时
go语言中可以实现go程的超时,Erlang也可以实现,不过更加方便,直接在receive里加上after,时间是以毫秒为单位。
sleep(Timeout)->
receive
after
Timeout->true
end.
echo()->
register(echo,spawn(?MODULE,loop,[])),
sleep(1000*3),
io:format("start send msg!"),
echo!{self(),hello},
receive
{From,Msg}->
io:format("~w~n",[Msg])
end,
From!stop.
loop()->
receive
{From,Msg}->
From!{self(),Msg},
loop();
stop->
ok
end.
五,性能测试
同时运行几万,几百万的进程来测试数据传递。
使用内置函数timer:tc(module,function,[args])来测试。
start(Num)->
start_proc(Num,self()).
start_proc(0,Pid)->
Pid!ok;
start_proc(Num,Pid)->
Npid=spawn(?MODULE,start_proc,[Num-1,Pid]),
Npid!ok,
receive
ok->
ok
end.