Erlangプログラム設計学習ノート(六)同時プログラミング
2895 ワード
Erlangプログラム設計学習ノート(六)同時プログラミング
きほんコンカレントかんすう
Pid = spawn(Mod , Func , Args)
apply(Mod,Func,Args)を実行する新しい同時プロセスを作成します.この新しいプロセスは呼び出しプロセスと並列に実行されます.spawnはPid(process identifierの略称、すなわちプロセス識別子)を返す.Pidでここに入ることができます
メッセージを送信します.要素数がlength(Args)のFunc関数は、Modモジュールからエクスポートする必要があります.新しいプロセスが作成されると、最新版のコード定義モジュールが使用されます.
Pid = spawn(Func)
Fun()を実行する新しい同時プロセスを作成します.この形式のspawnは、常に実行されるfunの現在の値を使用し、このfunはモジュールからエクスポートする必要はありません.
Pid!Message
識別子がPidのプロセスにメッセージメッセージメッセージを送信します.メッセージ送信は非同期です.送信側は待つのではなく、前の作業を続けます.送信オペレータと呼ばれます.
Pid ! MはMとして定義される.だから、Pid 1!Pid2 !...! Msgとは、メッセージMsgをPid 1、Pid 2などのすべてのプロセスに送信することを意味する.
receive ... end
プロセスに送信されたメッセージを受信
receive
Pattern1 [when Guard1] ->
Expression1:
Pattern2 [when Guard2] ->
Expression2:
...
end
メッセージがプロセスに到達すると、Pattern 1(およびオプションのレベルGuard 1)と一致しようとし、成功するとExpressions 1が実行されます.最初のパターンが一致しない場合は、Pattern 2を試してみます.一致するモードがない場合、メッセージは後で処理するために保存され、プロセスは次のメッセージを待機します.-module(area_server0).
-export([loop/0]).
loop()->
receive
{rectangle,Width,Hight} ->
io:format("Area of rectangle is ~p~n" , [Width *Hight]),
loop();
{square,Side} ->
io:format("Area of square is ~p~n" , [Side * Side]),
loop();
{_,_} ->
done
end.
Erlang Shell 1> cd("E:/workspace/HelloWorld/ebin").
E:/workspace/HelloWorld/ebin
ok
2> Pid = spawn(area_server0,loop,[]).
<0.35.0>
3> Pid ! {square , 4}.
Area of square is 16
{square,4}
4> Pid ! {rectangle , 4 , 5}.
Area of rectangle is 20
{rectangle,4,5}
spawn(area_server,loop,[])は実行area_を作成します.server:loop()のパラレルプロセスは、Pid、すなわち印刷された<0.35.0>に戻ります.
Pid ! {square , 4} . プロセスPidにメッセージが送信されます.このメッセージは{square,Side}に一致し、対応するメッセージが印刷されます.
タイマのシンプルな実装
-module(timer).
%% ====================================================================
%% API functions
%% ====================================================================
-export([start/2 , cancel/1]).
start(Time , Fun) ->
spawn(fun() -> mytimer(Time , Fun) end).
cancel(Pid)->Pid !cancel.
mytimer(Time , Fun)->
receive
cancel ->
void;
_ ->
ok
after Time->
Fun()
end.
1> cd("E:/workspace/Socket/ebin").
E:/workspace/Socket/ebin
ok
2> timer:start(5000, fun() -> io:format("timer count ~n") end).
<0.35.0>
timer count
3>
待ち時間が5秒を超えるとタイマーがトリガーされtimer countが出力されます
テール再帰
再帰関数で自分を呼び出すときに他の関数を呼び出さないでください.これにより、システム空間が枯渇する可能性があります.
loop()->
receive
{From , Expressiong1},
loop()
{From , Expressiong2},
loop()
%エラーの書き方ここで別の関数someFunc()を呼び出す
end
-module(area_server0).
-export([loop/0]).
loop()->
receive
{rectangle,Width,Hight} ->
io:format("Area of rectangle is ~p~n" , [Width *Hight]),
loop();
{square,Side} ->
io:format("Area of square is ~p~n" , [Side * Side]),
loop();
{_,_} ->
done
end.
1> cd("E:/workspace/HelloWorld/ebin").
E:/workspace/HelloWorld/ebin
ok
2> Pid = spawn(area_server0,loop,[]).
<0.35.0>
3> Pid ! {square , 4}.
Area of square is 16
{square,4}
4> Pid ! {rectangle , 4 , 5}.
Area of rectangle is 20
{rectangle,4,5}
-module(timer).
%% ====================================================================
%% API functions
%% ====================================================================
-export([start/2 , cancel/1]).
start(Time , Fun) ->
spawn(fun() -> mytimer(Time , Fun) end).
cancel(Pid)->Pid !cancel.
mytimer(Time , Fun)->
receive
cancel ->
void;
_ ->
ok
after Time->
Fun()
end.
1> cd("E:/workspace/Socket/ebin").
E:/workspace/Socket/ebin
ok
2> timer:start(5000, fun() -> io:format("timer count ~n") end).
<0.35.0>
timer count
3>