Erlang 基础学习 6 Concurrent Programming

好戏开始了

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园建设方案旨在通过融合先进技术,如物联网、大数据、人工智能等,实现校园的智能化管理与服务。政策的推动和技术的成熟为智慧校园的发展提供了基础。该方案强调了数据的重要性,提出通过数据的整合、开放和共享,构建产学研资用联动的服务体系,以促进校园的精细化治理。 智慧校园的核心建设任务包括数据标准体系和应用标准体系的建设,以及信息化安全与等级保护的实施。方案提出了一站式服务大厅和移动校园的概念,通过整合校内外资源,实现资源共享平台和产教融合就业平台的建设。此外,校园大脑的构建是实现智慧校园的关键,它涉及到数据中心化、数据资产化和数据业务化,以数据驱动业务自动化和智能化。 技术应用方面,方案提出了物联网平台、5G网络、人工智能平台等新技术的融合应用,以打造多场景融合的智慧校园大脑。这包括智慧教室、智慧实验室、智慧图书馆、智慧党建等多领域的智能化应用,旨在提升教学、科研、管理和服务的效率和质量。 在实施层面,智慧校园建设需要统筹规划和分步实施,确保项目的可行性和有效性。方案提出了主题梳理、场景梳理和数据梳理的方法,以及现有技术支持和项目分级的考虑,以指导智慧校园的建设。 最后,智慧校园建设的成功依赖于开放、协同和融合的组织建设。通过战略咨询、分步实施、生态建设和短板补充,可以构建符合学校特色的生态链,实现智慧校园的长远发展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值