Elixir学习笔记——进程(Processes)

news2024/11/25 22:36:11

在 Elixir 中,所有代码都在进程内运行。进程彼此隔离,彼此并发运行并通过消息传递进行通信。进程不仅是 Elixir 中并发的基础,而且还提供了构建分布式和容错程序的方法。

Elixir 的进程不应与操作系统进程混淆。Elixir 中的进程在内存和 CPU 方面非常轻量级(甚至与许多其他编程语言中使用的线程相比也是如此)。因此,同时运行数万甚至数十万个进程并不罕见。

在本章中,我们将学习生成新进程的基本构造,以及在进程之间发送和接收消息。

生成进程

生成新进程的基本机制是自动导入的 spawn/1 函数:

spawn/1 接受一个函数,它将在另一个进程中执行。

注意 spawn/1 返回一个 PID(进程标识符)。此时,您生成的进程很可能已死。生成的进程将执行给定的函数,并在函数完成后退出:

注意:您可能会获得与我们在代码片段中显示的不同进程标识符。

我们可以通过调用 self/0 来检索当前进程的 PID:

当我们能够发送和接收消息时,进程会变得更加有趣。

发送和接收消息

我们可以使用 send/2 向进程发送消息,并使用 receive/1 接收消息:

当消息发送到进程时,该消息存储在进程邮箱中。receive/1 块会遍历当前进程邮箱,搜索与任何给定模式匹配的消息。receive/1 支持保护和许多子句,例如 case/2。

发送消息的进程不会在 send/2 上阻塞,它会将消息放入收件人的邮箱并继续。特别是,进程可以向自己发送消息。

如果邮箱中没有与任何模式匹配的消息,则当前进程将等待,直到匹配的消息到达。还可以指定超时:

当您已经预计消息在邮箱中时,可以指定 0 的超时。

让我们将所有内容放在一起并在进程之间发送消息:

inspect/1 函数用于将数据结构的内部表示转换为字符串,通常用于打印。请注意,当执行接收块时,我们生成的发送方进程可能已经死亡,因为它的唯一指令是发送消息。

在 shell 中,您可能会发现辅助程序 flush/0 非常有用。它会刷新并打印邮箱中的所有消息。

链接

大多数情况下,我们在 Elixir 中生成进程时,都会将它们生成为链接进程。在展示 spawn_link/1 的示例之前,让我们看看当使用 spawn/1 启动的进程失败时会发生什么:

它只是记录了一个错误,但父进程仍在运行。这是因为进程是孤立的。如果我们希望一个进程中的失败传播到另一个进程,我们应该将它们链接起来。这可以通过 spawn_link/1 完成:

由于进程是链接的,我们现在看到一条消息,表示父进程(即 shell 进程)已收到来自另一个进程的 EXIT 信号,导致 shell 终止。IEx 检测到这种情况并启动新的 shell 会话。

也可以通过调用 Process.link/1 手动完成链接。我们建议您查看 Process 模块以了解进程提供的其他功能。

进程和链接在构建容错系统时起着重要作用。Elixir 进程是独立的,默认情况下不共享任何内容。因此,进程中的故障永远不会崩溃或破坏另一个进程的状态。但是,链接允许进程在发生故障时建立关系。我们经常将进程链接到主管,主管将检测进程何时死亡并代替其启动新进程。

虽然其他语言会要求我们捕获/处理异常,但在 Elixir 中,我们实际上可以允许进程失败,因为我们希望监督者能够正确重新启动我们的系统。“快速失败”(有时称为“让它崩溃”)是编写 Elixir 软件时的常见理念!

spawn/1 和 spawn_link/1 是 Elixir 中创建进程的基本原语。虽然到目前为止我们只使用它们,但大多数时候我们将使用在它们之上构建的抽象。让我们看看最常见的一个,称为任务。

任务

任务建立在 spawn 函数之上,以提供更好的错误报告和自省:

我们使用 Task.start/1 和 Task.start_link/1 而不是 spawn/1 和 spawn_link/1,它们返回 {:ok, pid} 而不仅仅是 PID。这使得任务可以在监督树中使用。此外,Task 提供了便利函数,如 Task.async/1 和 Task.await/1,以及简化分发的功能。

我们将在“Mix 和 OTP 指南”中探索围绕流程的任务和其他抽象。

状态

到目前为止,我们还没有讨论过状态。如果您正在构建一个需要状态的应用程序,例如,保存应用程序配置,或者您需要解析文件并将其保存在内存中,您会将其存储在哪里?

进程是这个问题最常见的答案。我们可以编写无限循环、保持状态以及发送和接收消息的进程。作为示例,让我们编写一个模块,该模块启动新进程,这些进程在名为 kv.exs 的文件中作为键值存储:

请注意,start_link 函数启动一个运行 loop/1 函数的新进程,从一个空映射开始。然后,loop/1(私有)函数等待消息并对每条消息执行适当的操作。我们使用 defp 而不是 def 将 loop/1 设为私有。对于 :get 消息,它会将消息发送回调用者并再次调用 loop/1,以等待新消息。而 :put 消息实际上使用新版本的映射调用 loop/1,并存储给定的键和值。

让我们通过运行 iex kv.exs 来尝试一下:

首先,进程图没有键,因此发送 :get 消息然后刷新当前进程收件箱将返回 nil。让我们发送 :put 消息并重试:

请注意进程如何保持状态,我们可以通过发送进程消息来获取和更新此状态。事实上,任何知道上述 pid 的进程都可以向其发送消息并操纵状态。

还可以注册 pid,为其命名,并允许知道该名称的每个人都向其发送消息:

使用进程来维护状态和名称注册是 Elixir 应用程序中非常常见的模式。但是,大多数时候,我们不会像上面那样手动实现这些模式,而是使用 Elixir 附带的众多抽象之一。例如,Elixir 提供了 Agents,它们是围绕状态的简单抽象。我们上面的代码可以直接写成:

还可以为 Agent.start_link/2 提供 :name 选项,它将自动注册。除了代理之外,Elixir 还提供了用于构建通用服务器(称为 GenServer)、注册表等的 API,所有这些都由底层进程提供支持。这些以及监督树将在“Mix 和 OTP 指南”中进行更详细的探讨,该指南将从头到尾构建一个完整的 Elixir 应用程序。

现在,让我们继续探索 Elixir 中的 I/O 世界。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1827489.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数学代码】幂

Hello!大家好,我是学霸小羊,今天来讲讲幂。 求几个相同因数的积的运算,叫做乘方,乘方的结果叫做幂。 a^n,读作 “ a的n次方 ” 或 “ a的n次方幂”,a叫做底数,n叫做指数。 对于底数、指数和幂…

开源高效API管理工具:RAP

RAP:简化API开发,提升团队协作效率- 精选真开源,释放新价值。 概览 RAP(RESTful API Project)是一个开源的API管理工具,由阿里巴巴团队开发并维护。它旨在帮助前后端开发人员通过一个统一的平台来设计、开…

《分析模式》漫谈03- Unified Method并不是RUP

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 在《分析模式》第2章 ,Fowler提到了“Rational Softwares Unified Method”, 而且给出了引用的参考文献,是Rational公司的一份文档: 200…

CSS入门到精通——表格样式

目录 表格边框 任务描述 相关知识 表格边框 折叠边框 编程要求 表格颜色、文字与大小 任务描述 相关知识 表格颜色 表格文字对齐与文字粗细 表格宽度和高度 任务要求 表格边框 任务描述 本关任务:在本关中,我们将学习如何使用CSS设置表格样…

基于carsim的线控转向仿真(1)--carsim车辆模型目标角度跟踪

一、Rwa转向执行总成建模 Rwa包括齿轮齿条机构、转向组件以及转向执行电机;如下图,电机输出轴通过齿轮减速增扭后,再经过一个半径为rp的小齿轮,直接带动齿条左右移动。齿条的移动通过转向摇臂,带动车轮转动&#xff0c…

Django初学者指南

文章目录 Django初学者指南1 Django简介1.1 Django的历史1.2 使用Django的知名网站1.4 Django的主要特点1.5 Django的工作原理 2 Django 使用2.1 Django 支持的 Python 版本2.2 Django 版本 3 Django 开发 Web 程序3.1 安装Django3.2 创建Django项目3.3 运行开发服务器3.4 创建…

【C++】【期末考】【基本概念和语法】概括总结——期末速成

目录 1. C简介 C的历史与发展 C的特点与优势 2. 基本语法 注释 数据类型与变量 常量 运算符 输入与输出 3. 控制结构 条件语句 循环语句 4. 函数 函数定义与声明 参数传递 返回值 函数重载 5. 数组与字符串 一维数组 多维数组 字符串处理 6. 指针 指针的…

数字电路中二进制的数据表达

文章目录 1. 二进制数据表达 1.1 二进制简介 1.2 用二进制表达文字 1.2.1 最开始的表达方式 1.2.2 通讯系统的编码和解码 1.2.3 集成电路 1.2.4 ASCII编码 1.2.5 GBK编码 1.2.6 Unicode编码 2. 用二进制表达图像 2.1 图片像素化 2.2 像素数字化 2.3 二值图像 2.4…

HTML+CSS 旋转呼吸加载器

效果演示 实现了一个旋转加载动画效果,包括一个圆形的加载框和两个不同颜色的圆形旋转动画。加载框和动画都使用了CSS的动画属性,实现了旋转和缩放的效果。整个加载动画的样式比较简单,使用了黑色和黄色的背景色,以及白色的文本颜…

哈希表、递归在二叉树中的应用-1372. 二叉树中的最长交错路径

题目链接及描述 1372. 二叉树中的最长交错路径 - 力扣(LeetCode) 题目分析 题目所述,计算在二叉树中交替遍历的最大深度【左->右->左】【右->左->右】,例如对于从当前根节点root出发,则此时遍历方向有两个…

【健身经验】2 圆肩

1、普拉提是针对小肌肉群锻炼,可以改善圆肩,圆肩就是因为背部没有力量,胸前也没有力量,因为平常没有用到这些肌肉 普拉提会用到小肌肉群,对于体态的纠正会比较好 2、肩背形态其实是发力问题,可以练习&…

springboot优雅shutdown时如何保障异步线程的安全

我前面写了一篇springboot优雅shutdown的文章,看起来一切很美好。 https://blog.csdn.net/chenshm/article/details/139640775 那是因为没有进行多线程测试。如果一个请求中包括阻塞线程(主线程)和非阻塞线程(异步线程&#xff09…

“二分图匹配策略:匈牙利算法详解与应用实践“

二分图的最大匹配 给定一个二分图,其中左半部包含 𝑛1 个点(编号 1∼𝑛1),右半部包含𝑛2 个点(编号1∼𝑛2),二分图共包含 𝑚 条边。 …

ollama 多模态llava图像识别理解模型使用

参考: https://llava-vl.github.io/ https://ollama.com/blog/vision-models https://blog.csdn.net/weixin_42357472/article/details/137666022 下载: ollama run llava:13bcli使用 图片地址前面空格就行 describe this image: /ai/a1.jpg

最新版点微同城源码34.7+全套插件+小程序前后端(含安装教程)

模板挺好看的 带全套插件 自己耐心点配置一下插件 可以H5可以小程序 源码下载:https://download.csdn.net/download/m0_66047725/89394996 更多资源下载:关注我。

维度建模中的事实表设计原则

维度建模是一种数据仓库设计方法,其核心是围绕业务过程建立事实表和维度表。事实表主要存储与业务过程相关的度量数据,而维度表则描述这些度量数据的属性。 以下是设计事实表时需要遵循的几个重要原则,来源于《维度建模》那本书上&#xff0…

正解 x86 Linux 内存管理

1,机器解析的思路 发现网络上大量的教程,多是以讹传讹地讲解 Linux 内存管理; 都是在讲: 逻辑地址 -> 线性地址 -> 物理地址 这个转换关系是怎么发生的。 上面这个过程确实是程序运行时地址的翻译顺序; …

Java课程设计:基于Javaweb的校园订餐系统

文章目录 一、项目介绍二、项目技术栈三、核心代码四、项目展示五、源码获取 一、项目介绍 在当今互联网高速发展的时代,大学校园内的学生生活正在发生着翻天覆地的变化。其中,校园内的餐饮服务无疑是亟需改革和创新的领域之一。 传统的校园食堂模式,往往存在就餐高峰时段拥挤…

[Cloud Networking] SPDY 协议

文章目录 1. 背景2. SPDY 之前3. SPDY 项目目标4. SPDY 功能特点4.1 SPDY基本功能4.2 SPDY高级功能 1. 背景 TCP是通用的、可靠的传输协议,提供保证交付、重复抑制、按顺序交付、流量控制、拥塞避免和其他传输特性。 HTTP是提供基本请求/响应语义的应用层协议。 不…

ubuntu 22.04下载和安装

ubuntu镜像: https://www.releases.ubuntu.com/22.04/ 然后下载vmwareworkstation16 密钥 ZF3R0-FHED2-M80TY-8QYGC-NPKYF