Erlang入门:gen_server实例操作与练习2

Eshell V5.10.4 (abort with ^G)

1> bank_server3:create_account(name1, 1000).

true

2> name1 ! check.

Current money is: 1000

check

3> erlang:send(name1, check).

Current money is: 1000

check

4> erlang:send(name1, abcd).

handle_info: abcd

abcd

Yearly Payment: 940 -> 880

5> gen_server:cast(name1, msg1).

handle_cast: msg1

ok

6> gen_server:cast(name123, msg1).

ok

7> name123 ! check.

** exception error: bad argument

in operator !/2

called as name123 ! check

Yearly Payment: 880 -> 820

8> gen_server:call(name1, msg1).

handle_call: msg1

ok

9> erlang:send(name1, stop1).

Receive STOP1

terminate: "Force STOP"

stop1

10>

=ERROR REPORT==== 15-Jan-2015::09:02:35 ===

** Generic server <0.34.0> terminating

** Last message in was stop1

** When Server state == 820

** Reason for termination ==

** "Force STOP"

Eshell V5.10.4 (abort with ^G)

1> bank_server3:create_account(name2, 1000).

true

2> name2 ! stop2.

Receive STOP2

terminate: normal

stop2

-module(bank_server3).
-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) ->
    ?I("handle_call: ~p", [Request]),
    Reply = ok,
    {reply, Reply, State}.

handle_cast(Msg, State) ->
    ?I("handle_cast: ~p", [Msg]),
    {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(stop1, Money) ->
    ?I("Receive STOP1"),
    Reason = "Force STOP",
    {stop, Reason, Money};

handle_info(stop2, Money) ->
    ?I("Receive STOP2"),
    Reason = normal,
    {stop, Reason, Money};

handle_info(Info, State) ->
    ?I("handle_info: ~p", [Info]),
    {noreply, State}.

terminate(Reason, _State) ->
    ?I("terminate: ~p", [Reason]),
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

时间: 2024-07-28 23:40:32

Erlang入门:gen_server实例操作与练习2的相关文章

Mybatis最入门---ResultMaps实例篇(一对多查询)

[一步是咫尺,一步即天涯] 接上文,我们来演示在实际开发中,如何配置和使用resultMap实现一对多查询. 准备工作: a.操作系统 :win7 x64 b.基本软件:MySQL,Mybatis,Spring,SQLyog,Tomcat,web基础 特别的,作为演示程序,还请各位看官不要纠结数据库的细节内容 ----------------------------------------------------------------------------------------------

【Git入门之四】操作项目

[Git入门之四]操作项目 - JackyStudio - 博客频道 - CSDN.NET 1.查看操作日记 <git log>用于查看操作日记详情.因为Git是分布式的,采用SHA1这样的版本号可有效的防止版本冲突. [cpp]?view plaincopy ? #查看操作日记,底下那串长长的数据就是SHA1?ID,表示当前版本号?? $Snbsp;git?log?? commit?aea0365712908805bc28540b4db9fd2f15360a8b?? Author:?Jack

Netty5快速入门及实例视频教程(整合Spring)

Netty5快速入门及实例视频教程+源码(整合Spring) https://pan.baidu.com/s/1pL8qF0J 01.传统的Socket分析02.NIO的代码分析03.对于NIO的一些疑惑04.Netty服务端HelloWorld入门05.Netty服务端入门补充06.Netty客户端入门07.如何构建一个多线程NIO系统08.Netty源码分析一09.Netty源码分析二10.Netty5服务端入门案例11.Netty5客户端入门案例12.单客户端多连接程序13.Netty学习

Socket通信入门小实例

客户端: public class Client { private int port = 8000; private String host = "localhost"; private Socket socket; public Client() throws UnknownHostException, IOException { socket = new Socket(host, port); } public void readFromUser() throws IOExcep

Thinkphp入门 二 —空操作、空模块、模块分组、前置操作、后置操作、跨模块调用(46)

原文:Thinkphp入门 二 -空操作.空模块.模块分组.前置操作.后置操作.跨模块调用(46) [空操作处理] 看下列图: 实际情况:我们的User控制器没有hello()这个方法 一个对象去访问这个类不存在的方法,那么它会去访问”魔术方法__call()” 用户访问一个不存在的操作—>解决:给每个控制器都定义个_empty()方法来处理 第二个解决方法:定义一个空操作 [空模块处理] 我们使用一个类,但是现在这个类还没有被include进来. 我们可以通过自动加载机制处理__autoloa

解决erlang和java同时操作一张表,造成锁表问题

作者:张昌昌 1.问题描述 Erlang端通过odbc去写oracle一张表,同时java通过jdbc驱动也去写这张表,当同时多次发生这种写操作时,这个表就被锁. 2.问题解决 思路:利用适配器原理,适配erlang和java的数据库连接,让erlang端对数据表的操作与java端对该数据表的操作,分时序顺序进行,其中一端在进行写操作时上锁 另一端就不能操作,直到他操作完成释放锁,另一端才能操作. 该适配器采用java编写,通过otp.jar让erlang与java进行通信,erlang和jav

QSqlQueryModel的实例操作

QSqlQueryModel类为SQL的结果集提供了一个只读的数据模型,下面我们先利用这个类进行一个最简单的操作. 我们新建Qt4 Gui Application工程,我这里工程名为queryModel ,然后选中QtSql模块,Base class选QWidget.工程建好后,添加C++ Header File ,命名为database.h,更改其内容如下: 1.           #ifndef DATABASE_H   2.             3.           #defin

Struts2+Spring+Ibatis用户注册、登录、管理入门学习实例源码下载

原文:Struts2+Spring+Ibatis用户注册.登录.管理入门学习实例源码下载 源代码下载地址:http://www.zuidaima.com/share/1550463735532544.htm Struts2+Spring+Ibatis用户注册.登录.管理入门学习实例源码下载 项目截图: jar包和sql文件都在源码包中. 运行截图: 用户注册页面: 用户管理页面:

[Sqlite]--&gt;嵌入式数据库事务理解以及实例操作

SQLite 事务(Transaction) 事务(Transaction)是一个对数据库执行工作单元.事务(Transaction)是以逻辑顺序完成的工作单位或序列,可以是由用户手动操作完成,也可以是由某种数据库程序自动完成. 事务(Transaction)是指一个或多个更改数据库的扩展.例如,如果您正在创建一个记录或者更新一个记录或者从表中删除一个记录,那么您正在该表上执行事务.重要的是要控制事务以确保数据的完整性和处理数据库错误. 实际上,您可以把许多的 SQLite 查询联合成一组,把所