erlang-并发编程_1、创建进程、进程中消息的传递、注册进程名称

写在前面

本文主要是以一个erlang的学习记录,有错误的地方欢迎指正。


erlang学习脑图

1.关于并发

串行是有很多任务要做,但要先完成一项之后才能,做接下去做另一项任务;
并发是指同时有很多的任务要去做,可以串行处理,也可以并行处理;
并行是指同时一起做多个任务。

2.创建进程

示例1:
使用erlang:spawn/1,2,3,4来创建一个erlang进程
在erlang shell 中输入


6> HelloSpawn = fun() -> io:format("hello Spawn") 
end.
%定义一个函数匹配给一个变量
#Fun<erl_eval.20.82930912>
7> spawn(HelloSpawn).
%spawn/1 BIF方法创建用一个函数做为一个参数数的进程
hello Spawn<0.41.0>
8> PID = pid(0.41.0).%符号输入错误导致语法报错
* 1: syntax error before: 0
8> PID = pid(0.41,0).%符号输入错误导致语法报异常
** exception error: undefined shell command pid/2
9> PID = pid(0,41,0).%检查是否是PID类型
<0.41.0>
10> is_pid(PID).
true
11> is_process_alive(PID).%%检查进程是否还活着
false
12> 

示例2:
运用内置函数spawn(Module,Exported_Function,list of Arguments)
新建进程示例:
新建文件tut14.erl,代码如下:

-module(tut14).
-export([start/0,
    say_something/2]).

%实现重复打印输入的内容,次数可配
say_something(What, 0) ->
    done;
    
say_something(What, Times) ->
    io:format("~p~n",[What]),
    say_something(What,Times -1).

start() ->
    spawn(tut14,say_something,[hello,3]),
    %启用一个新的进程,并发处理
    spawn(tut14,say_something,[goodbye,3]).

命令窗口输入如下:

➜  erlang erl
Erlang R15B03 (erts-5.9.3.1) [source] [64-bit] [smp:8:8] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.9.3.1  (abort with ^G)
1> c(tut14).
tut14.erl:7: Warning: variable 'What' is unused
{ok,tut14}
2> tut14:s
say_something/2  start/0          
2> tut14:say_something(hello123,3).
%%直接调用函数打出内容
hello123
hello123
hello123
done
3> tut14:start().  
%调用start()函数打出内容,                
hello
goodbye
<0.40.0>
%启用一个新的进程,并发处理
hello
goodbye
hello
goodbye

3.消息的传递

实现内容1:
从自己进程的信箱里发送消息和读取消息

注:erlang shell 也是一个进程,也有自已的pid.

17> self().%%self/1 返回当前进程的pid
<0.55.0>
18> 1=2.    %输入错误的对应关系,使当前的shell崩溃报错。
** exception error: no match of right hand side value 2
19> self(). %再查当前的进程pid,说明shell崩溃后重新启动了一个新的进程
<0.59.0>
20> 

3.1消息的发送

使用消息发送运算符!发送消息

20> self() ! "hello".
%向自已所在的进程发送一个list类型的“hello”
"hello"
21> flush().
% flush()将当前process(进程)的信箱里的内容清空并打印
Shell got "hello"
ok
22> 

3.2读取消息

receive ... end 语名使用pattern matching(匹配)来从自已的进程的信箱里读取消息,可以使用after语名来设置等待超时时间

38> self() ! "hello1".
"hello1"
39> self() ! "hello2".
"hello2"
40> self() ! "hello3".
"hello3"
41> receive Hello -> Hello after 3000 -> no_more end.
%% 读取任意消息并返回这条消息,如果信箱里没有消息了,等待 3 秒后结束并返回 no_more.
"hello1"
42> receive Hello -> Hello after 3000 -> no_more end.
no_more
43> receive Hello -> Hello after 3000 -> no_more end.
no_more
 %% 后面这两条为什么返回 no_more ? 不应该是 "hello2", "hello3" 吗?
44> 
44> flush().%打开信箱里的所有消息并清空
Shell got "hello2"
Shell got "hello3"
ok

上面的第 41 行 receive 语句里,erlang shell 进程查看邮箱,查到第一个消息是 "hello1",Hello 被绑定为 "hello1"。再次运行 receive 语句的时候,由于 Hello 的值已经为 "hello1",与信箱里的 "hello2", "hello3" 都不匹配,所以后面两条 receive 语句都没有从信箱里读取新消息,"hello2" 和 "hello2" 仍然存储在信箱里:

4.消息传递进阶

创建了两个进程,它们相互之间会发送多个消息
新建一个tut15.erl 文件,代码如下:

-module(tut15).

-export([start/0,
    ping/2,
    pong/0]).

ping(0,Pong_PID) ->
    Pong_PID ! finished,
    %向传过来的PID发送消息
    io:format("ping finished~n",[]);

ping(N,Pong_PID) ->
    Pong_PID ! {ping,self()},
    %向传过来的PID发送消息
    receive
        %%接收到传过来的消息,收到的消息为pong时,输入内容
        pong ->
            io:format("ping recevied pong~n",[])
    end,
    %重复调用,直到为N-1 为0
    ping(N - 1,Pong_PID).
        
pong() ->
    receive 
        finished -> %收到的消息为finished 时输入内容
            io:format("Pong finish ~n",[]);
        {ping,Ping_PID} ->
            io:format("Pong received ping~n",[]),
            Ping_PID ! pong,
            %向传过来的PID发送消息
            pong()%%自已调用自已,直到接收到finished,结束
    end.

start() ->
    Pong_PID = spawn(tut15, pong, []),
    spawn(tut15, ping, [3, Pong_PID]).

命令窗口输入命令如下:

4> c(tut15).
{ok,tut15}
5> tut15:start().
Pong received ping
<0.51.0>
ping recevied pong
Pong received ping
ping recevied pong
Pong received ping
ping recevied pong
ping finished
Pong finish 
6> 

5.Erlang 注册进程名称

Erlang 提供了为每个进程提供一个名称绑定的机制,这样进程间通信就可以通过进程名来实现,而不需要知道进程的进程标识符了。为每个进程注册一个名称需要用到内置函数 register:
关键代码:register(some_atom, Pid)

新建tut16.erl文件,代码如下:

-module(tut16).

-export([start/0,ping/1,pong/0]).

ping(0) ->
    pong ! finished,
    %发送信息
    io:format("ping finished~n",[]);

ping(N) ->
    pong ! {ping,self()},
    %发送信息,当前shell进程
    receive
        %接收消息并打印
        pong ->
            io:format("Ping received pong~n",[])
    end,
    ping(N - 1).

pong() ->
    receive
        finished ->
            %接收消息并打印
            io:format("pong finished~n",[]);
        {ping,Ping_PID} ->
            %接收消息并打印
            io:format("pong received ping~n",[]),
            Ping_PID ! pong,
            pong()
    end.

start() ->
    register(pong,spawn(tut16,pong,[])),
    %注册一个进程,命为pong
    spawn(tut16,ping,[3]).

命令窗口输入命令如下:

9> 
9> c(tut16).     
{ok,tut16}
10> tut16:start().
pong received ping
<0.71.0>
Ping received pong
pong received ping
Ping received pong
pong received ping
Ping received pong
ping finished
pong finished
11> 

写在后面

引用网络博客内容:
https://www.jianshu.com/p/b45eb9314d1e (30 分钟学 Erlang (一))
https://www.w3cschool.cn/erlang/tohb1p5z.html (w3cschool erlang教程)

个人博客地址:https://zhangyongfeng1.github.io/
简书地址:https://www.jianshu.com/u/137f325832fb

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341

推荐阅读更多精彩内容

  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 4,359评论 0 5
  • 世界是并行的,Erlang程序反应了我们思考和交流的方式,人作为个体通过发送消息进行交流,如果有人死亡,其他人会注...
    abel_cao阅读 2,738评论 1 4
  • 并发 创建进程 使用 erlang:spawn/1,2,3,4 用来创建一个 erlang 进程。Erlang 进...
    Shawn_xiaoyu阅读 13,785评论 9 22
  • 来源 RabbitMQ是用Erlang实现的一个高并发高可靠AMQP消息队列服务器。支持消息的持久化、事务、拥塞控...
    jiangmo阅读 10,341评论 2 34
  • 模式匹配是 Erlang 的根基,它被用于从数据结构中提取值,控制函数内部的流程,在并行程序中给进程发消息,选择处...
    Helperhaps阅读 1,378评论 0 1