热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Erlang入门:构建application练习4(进程link的作用)

1、示例项目(bank)简介bank_server.erl是为客户服务的进程回调模块bank_center.erl是为银行服务中心的进程回调模块客户(bank_serve

1、示例项目(bank)简介

技术分享

bank_server.erl是为客户服务的进程回调模块
bank_center.erl是为银行服务中心的进程回调模块
客户(bank_server)每年都要扣除年费
所有年费都交给银行服务中心(bank_center)

客户服务使用示例:
创建用户:bank_server:create_account(myname, 100).
用户存钱:myname ! {deposit, 10}.
用户取钱:myname ! {cash1, 20}.
myname ! {cash2, 30}.
查询余额:myname ! check.

银行服务中心使用示例:
查询收到的年费总额:bank_center ! check.


2、启动bank_center

2.1、bank_center里有3个启动API

%% 此处?MODULE为bank_center

start()->
%% gen_server:start/3
%% 无link,无注册
{ok, Pid} = gen_server:start(?MODULE, [], []),
%% 自行注册
erlang:register(?MODULE, Pid).

start2()->
%% gen_server:start/4
%% 无link,注册为本地进程,名称为?MODULE
gen_server:start({local, ?MODULE}, ?MODULE, [], []).

start_link()->
%% gen_server:start_link/4
%% 有link,有注册
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

用start/0或start2/0是无link的,start_link/0是有link的。

2.2、在bank_app里启动bank_center

-module(bank_app).
-behaviour(application). 
-export([start/2, stop/1]). 

-include("common.hrl").

start(_Type, _Args) -> 
?I("Start ~p ...", [?MODULE]),
% bank_center:start(),
% bank_center:start2(),
bank_center:start_link(),
{ok, self()}.

stop(_State) -> 
?I("Stop ~p!", [?MODULE]),
ok.

在上面start/2里调用bank_center:start/0或bank_center:start2/0启动后,
执行appmon:start()查看bank进程,如下:
技术分享
在上面start/2里调用bank_center:start_link/0启动后,
执行appmon:start()查看bank进程,如下:
技术分享

3、创建客户进程后,和bank_center进行link

bank_server.erl中的init/1
init([Money]) ->
%% 与银行服务中心进行关联
link(whereis(bank_center)),
{ok, Money}.

4、link实验

4.1、测试link的作用

link方式启动bank_center并且创建一个客户:
bank_server:create_account(myname1, 100).
whereis(bank_center)查看bank_center进程ID,返回不为undefined说明bank_center进程存在
向客户进程发送一个错误:
myname1 ! error.
此时myname1异常退出,whereis(bank_center)和whereis(myname1)都返回undefined,说明这两个进程都已经终止。
Eshell V5.10.4 (abort with ^G)
1> bank_server:create_account(myname1, 100).
true
2> whereis(bank_center).
<0.37.0>
3> myname1 ! error.
##[<0.38.0>bank_server:141] terminate: {bad_return_value,{ok,80}}
error
4> 
=ERROR REPORT==== 16-Jan-2015::16:54:58 ===
** Generic server <0.38.0> terminating 
** Last message in was error
** When Server state == 80
** Reason for termination == 
** {bad_return_value,{ok,80}}

4> whereis(bank_center).
undefined
5> whereis(myname1). 
undefined
小结:用link进行关联的进程组中,只要其中一个进程终止,其他也会同时终止。

4.2、设置bank_center为系统进程,并且能监控客户进程的退出

设置bank_center为系统进程:
bank_center.erl中的init/1
init(_) ->
%% 把系统进程设置为系统进程
process_flag(trap_exit, true),
?I("Start ~p ...", [?MODULE]),
{ok, 0}.
演示过程如下:
Eshell V5.10.4 (abort with ^G)
1> bank_server:create_account(myname1, 100).
true
2> 
2> myname1 ! error.
##[<0.38.0>bank_server:141] terminate: {bad_return_value,{ok,100}}
##[<0.37.0>bank_center:81] handle_info: {&#39;EXIT&#39;,<0.38.0>,
{bad_return_value,{ok,100}}}
error
3> 
=ERROR REPORT==== 16-Jan-2015::17:12:34 ===
** Generic server <0.38.0> terminating 
** Last message in was error
** When Server state == 100
** Reason for termination == 
** {bad_return_value,{ok,100}}

3> whereis(bank_center).
<0.37.0>
4> whereis(myname1). 
undefined
whereis(myname1).返回undefined说明已经终止。
whereis(bank_center)返回了PID,说明没有终止,并且收到了myname1的退出消息:
{&#39;EXIT&#39;, <0.38.0>, {bad_return_value,{ok,100}}}
消息中指明了退出的PID及退出原因。
以上都是以异常的方式让进程退出的,现在测试一下正常退出的情况:
Eshell V5.10.4 (abort with ^G)
1> bank_server:create_account(myname1, 100).
true
2> myname1 ! stop2.
##[<0.38.0>bank_server:141] terminate: normal
##[<0.37.0>bank_center:81] handle_info: {&#39;EXIT&#39;,<0.38.0>,normal}
stop2
正常退出不会报错,收到了正常退出消息:{‘EXIT‘,<0.38.0>,normal}

小结:通过process_flag(trap_exit, true)将进程设置为系统,不但不会随着别的进程退出而退出,还能监控其他进程的退出情况。
问题:如果系统进程内部发生了错误而异常退出,将会出现什么情况?


5、完整演示代码下载

地址:http://download.csdn.net/detail/u011471961/8368973

Erlang入门:构建application练习4(进程link的作用)


推荐阅读
  • malloc 是 C 语言中的一个标准库函数,全称为 memory allocation,即动态内存分配。它用于在程序运行时申请一块指定大小的连续内存区域,并返回该区域的起始地址。当无法预先确定内存的具体位置时,可以通过 malloc 动态分配内存。 ... [详细]
  • NX二次开发:UFUN点收集器UF_UI_select_point_collection详解
    本文介绍了如何在NX中使用UFUN库进行点收集器的二次开发,包括必要的头文件包含、初始化和选择点集合的具体实现。 ... [详细]
  • JUC(三):深入解析AQS
    本文详细介绍了Java并发工具包中的核心类AQS(AbstractQueuedSynchronizer),包括其基本概念、数据结构、源码分析及核心方法的实现。 ... [详细]
  • 在多线程并发环境中,普通变量的操作往往是线程不安全的。本文通过一个简单的例子,展示了如何使用 AtomicInteger 类及其核心的 CAS 无锁算法来保证线程安全。 ... [详细]
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • 在HTML布局中,即使将 `top: 0%` 和 `left: 0%` 设置为元素的定位属性,浏览器中仍然会出现空白填充。这个问题通常与默认的浏览器样式、盒模型或父元素的定位方式有关。为了消除这些空白,可以考虑重置浏览器的默认样式,确保父元素的定位方式正确,并检查是否有其他CSS规则影响了元素的位置。 ... [详细]
  • 在分析和解决 Keepalived VIP 漂移故障的过程中,我们发现主备节点配置如下:主节点 IP 为 172.16.30.31,备份节点 IP 为 172.16.30.32,虚拟 IP 为 172.16.30.10。故障表现为监控系统显示 Keepalived 主节点状态异常,导致 VIP 漂移到备份节点。通过详细检查配置文件和日志,我们发现主节点上的 Keepalived 进程未能正常运行,最终通过优化配置和重启服务解决了该问题。此外,我们还增加了健康检查机制,以提高系统的稳定性和可靠性。 ... [详细]
  • 在 Android 开发中,`android:exported` 属性用于控制组件(如 Activity、Service、BroadcastReceiver 和 ContentProvider)是否可以被其他应用组件访问或与其交互。若将此属性设为 `true`,则允许外部应用调用或与之交互;反之,若设为 `false`,则仅限于同一应用内的组件进行访问。这一属性对于确保应用的安全性和隐私保护至关重要。 ... [详细]
  • 本文介绍 DB2 中的基本概念,重点解释事务单元(UOW)和事务的概念。事务单元是指作为单个原子操作执行的一个或多个 SQL 查询。 ... [详细]
  • 使用ArcGIS for Java和Flex浏览自定义ArcGIS Server 9.3地图
    本文介绍了如何在Flex应用程序中实现浏览自定义ArcGIS Server 9.3发布的地图。这是一个基本的入门示例,适用于初学者。 ... [详细]
  • 本文介绍了如何在 Vue 3 组合 API 中正确设置 setup() 函数的 TypeScript 类型,以避免隐式 any 类型的问题。 ... [详细]
  • WinMain 函数详解及示例
    本文详细介绍了 WinMain 函数的参数及其用途,并提供了一个具体的示例代码来解析 WinMain 函数的实现。 ... [详细]
  • IOS Run loop详解
    为什么80%的码农都做不了架构师?转自http:blog.csdn.netztp800201articledetails9240913感谢作者分享Objecti ... [详细]
  • [转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ... [详细]
  • 优化Vite 1.0至2.0升级过程中遇到的某些代码块过大问题解决方案
    本文详细探讨了在将项目从 Vite 1.0 升级到 2.0 的过程中,如何解决某些代码块过大的问题。通过具体的编码示例,文章提供了全面的解决方案,帮助开发者有效优化打包性能。 ... [详细]
author-avatar
路很长别太狂_297
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有