辅助函数
% 计算T1,T2之间相隔的时间
deta_time(T1, T2) ->
{M1, S1, _} = T1,
{M2, S2, _} = T2,
(M2-M1)*1000000 + (S2-S1).
deta_time(T1) ->
T2 = os:timestamp(),
deta_time(T1, T2).
% (1) 编写一个my_spawn(Mod, Func, Args)函数。它的行为类似spawn(Mod, Func, Args),
但有一点区别。如果分裂出的进程挂了,就应打印一个消息,说明进程挂掉的原因以及在此之前
存活了多长时间。
my_spawn(Mod, Func, Args) ->
T1= os:timestamp(),
{Pid, Ref} = spawn_monitor(Mod, Func, Args),
receive
{'DOWN', Ref, process, Pid, Why} ->
io:format("donw.~p:~p, dt:~p", [Pid, Why, deta_time(T1)])
end.
(2) 用本章前面展示的on_exit函数来完成上一个练习。
on_exit(Pid, Fun) ->
spawn(
fun() ->
Ref = monitor(process, Pid) ,
receive
{'DOWN', Ref, process, Pid, Why} ->
Fun(Why)
end
end).
my_spawn2(Mod, Func, Args) ->
T1 = os:timestamp(),
Pid = spawn(Mod, Func, Args),
on_exit(Pid, fun()->
io:format("~p~n", deta_time(T1))
end).
(3) 编写一个my_spawn(Mod, Func, Args, Time)函数。它的行为类似spawn(Mod, Func,
Args),但有一点区别。如果分裂出的进程存活超过了Time秒,就应当被摧毁。
my_spawn3(Mod, Func, Args, Time) ->
{Pid, Ref} = spawn_monitor(Mod, Func, Args),
receive
{'DOWN', Ref, process, Pid, Why} ->
over
after Time*1000 ->
exit(Pid, "KILL")
end.
(4) 编写一个函数,让它创建一个每隔5秒就打印一次“我还在运行”的注册进程。编写一个
函数来监视这个进程,如果进程挂了就重启它。启动公共进程和监视进程,然后摧毁公共进程,
检查它是否会被监视进程重启。
create_fun() ->
Loop = fun(Af) ->
receive
after 1000 ->
io:format("~2.2.0w:~2.2.0w:~2.2.0w I'm running.~n", tuple_to_list(time())),
{_, _, S} = time(),
if
S rem 10 =:= 0 ->
exit("Test: 10 seconds exit.");
true ->
Af(Af)
end
end
end,
spawn(fun() ->
Loop(Loop)
end).
monitor_fun() ->
Pid = create_fun(),
monitor(process, Pid),
receive
{'DOWN', Ref, process, Pid, Why} ->
io:format("~p exit, Why:~p~n", [Pid, Why]),
monitor_fun()
end.
(5) 编写一个函数来启动和监视多个工作进程。如果任何一个工作进程非正常终止,就重启它。
work(Name) ->
WorkTime = rand:uniform(10),
io:format("~p will work ~w second.~n", [Name, WorkTime]),
receive
after WorkTime*1000 ->
exit(io:format(" ~p ~p~n", ["Job Down! ", Name]))
end.
myMonitor(M) ->
receive
{'DOWN', Ref, process, _, _} ->
case maps:is_key(Ref, M) of
true ->
F = maps:get(Ref, M),
NM = maps:remove(Ref, M), %移除旧的数据
{_, R} = spawn_monitor(F),
myMonitor(NM#{R=>F});
false ->
ignore
end
end.
bigMonitor() ->
F1 = fun() -> work(jack) end,
{_, R1} = spawn_monitor(F1),
F2 = fun() -> work(lily) end,
{_, R2} = spawn_monitor(F2),
myMonitor(#{R1=>F1, R2=>F2}).
(6)参考5,略
看书的时候感觉自己会了, 不写不知道,其实自己还不会,或者理解的有偏差。