黄小华的个人网站
熬过无人问津的日子才有诗和远方!
gen_server和gen_fsm

一. 相同点(特点):

  1. 启动进程通信
    gen_server和gen_fsm都是通过gen模块来启动一个持续recv的进程,监听着进程外给自己发送的消息,或者是自己给自己发送的消息。
  2. 维护消息队列(消息邮箱)
    gs和gf都维护了一个消息邮箱,类似于消息队列的数据结构,存储着进程收到的所有消息。在消息队列不为空时,会向消息队列获取消息,并消费消息,对消息做出对应的处理。
  3. 唯一进程消息处理与分发
    从模块方法上看,erleng 的gs和gf都是通过gen_server与gen_fsm模块统一调用和消息分发。
    以gen_server为例,start_link()方法是其实是在gen_server方法进程里以模块名为pid的方式进行了注册
    调用方式是由gen_server的cast或者call方法,gen_server会在进程中找到对应模块的pid,然后进行转发。
    通过消息的传递从而达到多模块之间互相调用的效果。
    消息的处理方式以及具体逻辑由自己模块的回调函数决定
    模块调用handle方法实际上由自己决定。因为gen_server对cast与call方法都进行了一定的消息封装
    标记了-behavior(gen_server)的进程可以自动解析带有特殊封装的消息然后调用handlecast或handlecall方法。
    不包含特殊封装的方法则会全都调用handle_info方法来进行接收。多个方法实现了对所有消息的处理。
    回调函数都包含了基本的init handle_info terminate code_change方法。对模块的初始化,退出,状态变化,普通消息接收都进行了类似的处理。
    二. 不同点
  4. 消息封装方式与api
    gen_server与gen_fsm的消息封装方式不同,回调函数也不同(具体可以查看官方文档说明)
  5. 主要结构特点与应用场景
    2.1 gen_server
    gen_server仅仅只维持一个存储数据的State来作为参与模块调用全过程的状态参数,可以用来存储基于模块的需要维护的数据。State不影响函数的跳转流程,只影响回调函数的处理逻辑。
    gen_server较于gen_fsm消息处理方式更为简单,只是包含了同步,异步,普通消息处理,以及正常的初始化等方法。
    gen_server具备较强的拓展性,可以支持作为fsm类型的状态变化模块的编程实现,也可以支持例如简单的数据处理,消息收发,消息转发,模块调用等可以基于消息传输的大部分模块功能。
    2.2 gen_fsm
    作为参数传递的有2个参数,一个是当前状态名StateName以及当前模块需要维护的数据State
    gen_fsm相对与gen_server的简单异步,同步方法进行了更加细 化的区别。
    拆分出了基于状态的同步、异步方法以及影响全局的同步,异步方法
    分别需要gen_fsm的behavior模块提供对应的4种回调函数
    gen_fsm也提供了四种不同的特殊消息传递方法
    gen_fsm的基于状态的同步,异步方法可以由gen_server实现,例如
    基于状态的同步方法,可以编写gen_server的特定参数的handle_call回调方法接收并处理
    timout方法也可以通过调用带有参数timeout的回调函数实现超时状态转换。
    gen_fsm的StateName也可以通过gen_server存储在State里作为持续参数来实现 gen_fsm的不同状态
    gen_fsm的基于状态不同的不同回调函数的实现
  6. 功能区别
    gen_server对于回调函数的调用只是基于handleinfo handlecast handlecall 三个基本方法。而gen_fsm则拓展了基于函数名的回调函数 gen_fsm可以通过设定多种状态,实现多种回调函数来实现多个状态的跳转。虽然gen_server也可以通过编程做到这一点,但是gen_fsm可以更加简洁清晰得实现这类方法。
    gen_fsm较于gen_server更加注重timeout参数的使用以及状态函数的timeout处理。gen_fsm在设置了超时时间后会在超时后自动发送timeout消息(与gen_fsm:send_event类似),以event的方式对状态进行调用处理,实现多状态之间的自动跳转。
    gen_fsm适合应用在实现一个基于状态的模块。维护一个模块的不同状态,同时,模块在接收消息后会对消息携带的时间做出反应,状态随之发生变化。多个状态之间可以进行循环的切换。
    屏幕截图 20210323 151020.png