在改進(jìn) messager 程序之前,讓我們一起學(xué)習(xí)一些基本的原則?;貞浺幌拢?dāng) “ping” 結(jié)束的時(shí)候,它向 “pong” 發(fā)送一個(gè)原子值 finished 的消息以通知 “pong” 結(jié)束程序。另一種讓 “pong” 結(jié)束的辦法是當(dāng) “pong” 有一定時(shí)間沒有收到來(lái)自 “ping” 的消息時(shí)則退出程序。我們可在 pong 中添加一個(gè) time-out 來(lái)實(shí)現(xiàn)它:
-module(tut19).
-export([start_ping/1, start_pong/0, ping/2, pong/0]).
ping(0, Pong_Node) ->
io:format("ping finished~n", []);
ping(N, Pong_Node) ->
{pong, Pong_Node} ! {ping, self()},
receive
pong ->
io:format("Ping received pong~n", [])
end,
ping(N - 1, Pong_Node).
pong() ->
receive
{ping, Ping_PID} ->
io:format("Pong received ping~n", []),
Ping_PID ! pong,
pong()
after 5000 ->
io:format("Pong timed out~n", [])
end.
start_pong() ->
register(pong, spawn(tut19, pong, [])).
start_ping(Pong_Node) ->
spawn(tut19, ping, [3, Pong_Node]).
編譯上面的代碼并將生成的 tut19.beam 文件拷貝到某個(gè)目錄下,下面是在結(jié)點(diǎn) pong@kosken 上的輸出:
true
Pong received ping
Pong received ping
Pong received ping
Pong timed out
在結(jié)點(diǎn) ping@gollum 上的輸出結(jié)果為:
(ping@gollum)1> tut19:start_ping(pong@kosken).
<0.36.0>
Ping received pong
Ping received pong
Ping received pong
ping finished
time-out 被設(shè)置在:
pong() ->
receive
{ping, Ping_PID} ->
io:format("Pong received ping~n", []),
Ping_PID ! pong,
pong()
after 5000 ->
io:format("Pong timed out~n", [])
end.
執(zhí)行 recieve 時(shí),超時(shí)定時(shí)器 (5000 ms)啟動(dòng);一旦收到 {ping,Ping_PID} 消息,則取消該超時(shí)定時(shí)器。如果沒有收到 {ping,Ping_PID} 消息,那么 5000 毫秒后 time-out 后面的程序就會(huì)被執(zhí)行。after 必須是 recieve 中的最后一個(gè),也就是說(shuō),recieve 中其它所有消息的接收處理都優(yōu)先于超時(shí)消息。如果有一個(gè)返回值為整數(shù)值的函數(shù),我們可以在 after 后調(diào)用該函數(shù)以將其返回值設(shè)為超時(shí)時(shí)間值,如下所示:
after pong_timeout() ->
一般地,除了使用超時(shí)來(lái)監(jiān)測(cè)分布式 Erlang 系統(tǒng)的各分部外,還有許多更好的辦法來(lái)實(shí)現(xiàn)監(jiān)測(cè)功能。超時(shí)適用于監(jiān)測(cè)來(lái)自于系統(tǒng)外部的事件,比如說(shuō),當(dāng)你希望在指定時(shí)間內(nèi)收到來(lái)自外部系統(tǒng)的消息的時(shí)候。舉個(gè)例子,我們可以用超時(shí)來(lái)發(fā)現(xiàn)用戶離開了messager 系統(tǒng),比如說(shuō)當(dāng)用戶 10 分鐘沒有訪問系統(tǒng)時(shí),則認(rèn)為其已離開了系統(tǒng)。
更多建議: