自定义让当前进程sleep T毫秒的方法
- sleep(T) ->
- receive
- after T ->
- true
- end.
自定义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.
每个进程都有一个mailbox
发送消息到该进程时,消息被放入mailbox
当程序运行到receive语句时,启动一个timer
读取mailbox中的第一条消息,匹配Pattern1,2,...,如果消息匹配了,则从mailbox中删除掉,并执行该Pattern后的表达式
如果receive语句中没有匹配的Pattern,则将该消息从mailbox中删除并放入save queue,然后下一条消息进来匹配
如果mailbox中没有一条消息是匹配成功的,则进程suspend并等待下一次新的消息进来,下次有新消息时save queue里的消息不会再匹配
一旦有消息匹配,则已经放入save queue的消息按到达进程的顺序重新进入mailbox,如果设置了timer,则清空save queue
如果在等待消息时timer到点,则执行ExpressionsTimeout表达式并将保存的消息按到达进程的顺序放入mailbox
publishing一个process identifier,这样系统里所有process都可以和这个process交互,发布的process称为registered process
BIFs:
- register(AnAtom, Pid)
- unregister(AnAtom)
- whereis(AnAtom) -> Pid | undefined
- registered() -> [AnAtom::atom()]
Example
- 1> Pid = spawn(fun area_server:loop/0).
- <0.51.0>
- 2> register(area, Pid).
- true
- 3> area ! {rectangle, 4, 5}.
- Area of rectangle is 20
- {rectangle,4,5}
Example2
- -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.
- %%%%%%%%%%%%%%%%%%
- 1> clock:start(5000, fun() -> io:format("TICK ~p~n", [erlang:now()]) end).
- 2> clock:stop().
Concurrent Program Template
- -module(ctemplate).
- -compile(export_all).
- start() ->
- spawn(fun() -> loop([]) end).
- rpc(Pid, Request) ->
- Pid ! {self(), Request},
- receive
- {Pid, Response} ->
- Response
- end.
- loop(X) ->
- receive
- Any ->
- io:format("Received:~p~n", [Any]),
- loop(X)
- end.
在loop里receive之后马上又调用loop,则loop称为tail-recursive方法
如果我们写一个方法F,F never returns,则需要确保在调用F之后不会调用其他方法,也不要将F用于List或Tuple的constructor,否则内存溢出
spawn with MFA:
- spawn(Mod, FuncName, Args)
使用Mod名、Func名和Args列表(成为一个MFA)来显式的调用spawn是确保系统动态加载代码(热修改)的正确方式
spawn with funs则不会动态加载代码