7.Erlang 并发编程

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.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值