Erlang入门:gen_server实例操作与练习1
2015-01-15 09:35
459 查看
%% @author Rolong<rolong@vip.qq.com> -module(bank_test1). -compile(export_all). %% 假设我开了3个银行账户: %% %% bank_server2:create_account(name1, 100). %% bank_server2:create_account(name2, 100). %% bank_server2:create_account(name3, 100). %% %% 练习1:如何获取name1对应的pid? %% %% 解答1:Pid1 = whereis(name1). %% %% %% 练习2:实现一个函数,计算以上3个账户余额的总和。 %% %% bank_sum(name1, name2, name3) -> Result. %% %% Result 为账号name1, name2, name3三个账户余额的总和。 %% 练习2解答思路: %% 1、先实现获取一个账户余额的API %% 1.1、用receive原语实现 bank_check(Name) -> Pid = whereis(Name), Pid ! {self(), check}, receive {Pid, Money} -> Money end. %% 1.2、用gen_server:call/2实现 bank_check2(Name) -> gen_server:call(Name, check). %% 2、实现bank_sum函数 %% 2.1、普通实现 bank_sum(N1, N2, N3) -> M1 = bank_check2(N1), M2 = bank_check2(N2), M3 = bank_check2(N3), M1 + M2 + M3. %% 2.2、递归实现 bank_sum2(Names) -> bank_sum2(Names, 0). bank_sum2([Name | T], Sum) -> Sum1 = Sum + bank_check2(Name), bank_sum2(T, Sum1); bank_sum2([], Sum) -> Sum.
-module(bank_server2).
-behaviour(gen_server).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-export([create_account/2]).
-define(I(F), io:format(F++"~n", [])).
-define(I(F, A), io:format(F++"~n", A)).
% --------------------------------------------------------------------
% API
% --------------------------------------------------------------------
%%'银行开户,并存入初始金额
-spec create_account(Name, Money) -> any() when
Name :: atom(),
Money :: integer().
create_account(Name, Money)->
%% gen_server:start(Mod, Args, Options)
{ok, Pid} = gen_server:start(?MODULE, [Money], []),
%% 假设年费为10
Pid ! {yearly, 60},
erlang:register(Name, Pid).
% --------------------------------------------------------------------
% Callback
% --------------------------------------------------------------------
init([Money]) ->
{ok, Money}.
handle_call(check, _From, Money) ->
{reply, Money, Money};
handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
%%'存钱
handle_info({deposit, AddMoney}, Money) ->
NewMoney = Money + AddMoney,
?I("deposit money: ~w -> ~w", [Money, NewMoney]),
{noreply, NewMoney};
%%.
%%'取钱(可透支)
handle_info({cash1, SubMoney}, Money) ->
NewMoney = Money - SubMoney,
?I("deposit money: ~w -> ~w", [Money, NewMoney]),
{noreply, NewMoney};
%%.
%%'取钱(不可透支)
handle_info({cash2, SubMoney}, Money) ->
NewMoney = Money - SubMoney,
case NewMoney > 0 of
true ->
%% 支取成功
?I("deposit money: ~w -> ~w", [Money, NewMoney]),
{noreply, NewMoney};
false ->
%% 支取失败 提示余额不足
?I("Insufficient balance, current money is ~w", [Money]),
{noreply, Money}
end;
%%.
%%'扣年费(这里假设10秒为一年)
handle_info({yearly, Payment}, Money) ->
Year = case get(year) of
undefined ->
put(year, 0),
0;
Y ->
YY = Y + 1,
put(year, YY),
YY
end,
erlang:send_after(60 * 1000, self(), {yearly, Payment}),
Reply = if
Money =< 0 ->
%% 没有钱可以扣
Money;
Year =:= 0 ->
%% 还不到一年,不用扣
Money;
true ->
NewMoney = Money - Payment,
case NewMoney > 0 of
true ->
%% 扣费成功
?I("Yearly Payment: ~w -> ~w", [Money, NewMoney]),
NewMoney;
false ->
%% 余额不足以扣年费,则扣到0为止
?I("Yearly Payment: ~w -> ~w", [Money, 0]),
0
end
end,
{noreply, Reply};
%%.
%%'查询
handle_info(check, Money) ->
?I("Current money is: ~w", [Money]),
{noreply, Money};
handle_info({From, check}, Money) ->
%% ?I("Send result to: ~w", [From]),
From ! {self(), Money},
{noreply, Money};
%%.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
相关文章推荐
- Erlang入门:gen_server实例操作与练习2
- Erlang入门:进程实例操作与练习1
- Erlang入门:服务进程实例操作与练习3
- Erlang入门:进程实例操作与练习2
- Erlang入门:服务进程实例操作与练习1
- Erlang入门:服务进程实例操作与练习2
- Erlang入门:进程实例操作与练习3(选修)
- Erlang入门:gen_server代码模板
- erlang behaviour小结之gen_server OTP入门
- erlang gen_server实例
- Erlang gen_server进程调用实例
- javascript JSON操作入门实例
- 18个小实例入门SQLServer XML查询
- castle ActiveRecord入门实例(1)-单表操作
- Erlang gen_server:start_link/3 和gen_server:start_link/4
- Erlang gen_server:start_link/3 和gen_server:start_link/4
- sed与Awk教程入门与实例练习(ZZ)
- [erlang 学习] 转载的 gen_server中管理新的进程
- erlang(2) gen_server
- erlang(2) gen_server