Elixir学习笔记——进程(Processes)
在 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 世界。
相关文章:
Elixir学习笔记——进程(Processes)
在 Elixir 中,所有代码都在进程内运行。进程彼此隔离,彼此并发运行并通过消息传递进行通信。进程不仅是 Elixir 中并发的基础,而且还提供了构建分布式和容错程序的方法。 Elixir 的进程不应与操作系统进程混淆。Elixir 中的进程在内存和 CPU…...
困惑度作为nlp指标的理解示例
为了更清晰地说明困惑度的计算过程以及如何通过困惑度判断模型的优劣,我们可以通过一个简单的例子来演示。假设我们有一个非常简单的文本语料库和两个基础的语言模型进行比较。 示例文本 假设我们的文本数据包括以下两个句子: “cat sits on the mat”…...
01 Pytorch 基础
paddle不需要放数据到gpu! 区别:1.batch_norlization 不同 2. 1.数据处理 1.取一个数据,以及计算大小 (剩下的工作,取batch,pytorch会自动做好了) 2.模型相关 如何得到结果 3.模型训练/模型…...
STL——set、map、multiset、multimap的介绍及使用
文章目录 关联式容器键值对树形结构与哈希结构setset的介绍set的使用set的模板参数列表set的构造set的使用set的迭代器使用演示 multisetmultiset演示 mapmap的定义方式map的插入map的查找map的[ ]运算符重载map的迭代器遍历multimapmultimap的介绍multimap的使用 在OJ中的使用…...
使用C语言,写一个类似Linux中执行cat命令的类似功能
一、详细的代码案例 #include <stdio.h> #include <stdlib.h> #include <string.h>// 函数声明 void cat_file(const char *filename);int main(int argc, char *argv[]) {if (argc < 2) {fprintf(stderr, "Usage: %s filename1 [filename2 ...]\n&…...
【Android】Android系统性学习——Android系统架构
前言 部分内容参考《Android进阶解密》 – 刘望舒 1. Android版本 官方链接:https://developer.android.com/studio/releases/platforms 里面有各个版本的官方文档,有些新功能的用法在这里面。 现在做安卓11,有时候需要向下兼容 2. AOSP …...
鸿蒙应用开发
学习视频: 00.课程介绍_哔哩哔哩_bilibili 官网:开发者文档中心 | 华为开发者联盟 (huawei.com) 开发工具 :DevEcoStudio , 类似Jetbrains 全家桶 ArkTS开发语言 :(基于TS,集成了前端语言…...
索引失效有效的11种情况
1全职匹配我最爱 是指 where 条件里 都是 ,不是范围(比如>,<),不是 不等于,不是 is not null,然后 这几个字段 建立了联合索引 ,而且符合最左原则。 那么就要比 只建…...
字符数组基础知识及题目
死识。。。 字符该如何存储呢?这一点我们在以前就接触过了。用char来存储。 如何输入一个单词呢? char a[10002]; scanf("%s",a); 就不用地址符了。 如何输入句子呢? char a[100002]; gets(a); gets是读入句子的,…...
一个简单的玩具机器人代码
编写一个玩具机器人脚本通常取决于机器人的硬件、接口和具体功能。然而,由于我们不能直接控制一个真实的硬件机器人,所以只是写一个模拟的C语言脚本示例,该脚本描述了一个简单的玩具机器人可能执行的一些基本操作。 假设我们的“玩具机器人”…...
设计模式-装饰器模式Decorator(结构型)
装饰器模式(Decorator) 装饰器模式是一种结构模式,通过装饰器模式可以在不改变原有类结构的情况下向一个新对象添加新功能,是现有类的包装。 图解 角色 抽象组件:定义组件的抽象方法具体组件:实现组件的抽象方法抽象装饰器&…...
RK3588开发板中使用Qt对zip文件进行解压
操作步骤: 下载源码quazip-0.7.3.zip ,在网上找找下载地址上传源码进行解压,然后使用命令 cd quazip-0.7.3 qmake make主要用的是quazip-0.7.3/quazip这个里面的源码,然后把源码加入到自己创建的qt项目pro中,导入方式…...
三、网络服务协议
目录 一、FTP:文件传输协议 二、Telnet:远程登录协议 三、AAA认证 四、DHCP 五、DNS 六、PPP协议 七、ISIS协议 一、FTP:文件传输协议 C/S架构,现多用于企业内部的资料共享和网络设备的文件传输,企业内部搭建一…...
C++初学者指南第一步---1. C++开发环境设置
C初学者指南第一步—1. C开发环境设置 目录 C初学者指南第一步---1. C开发环境设置1.1 工具1.1.1 代码编辑器和IDE1.1.2 Windows1.1.3 命令行界面 1.2 编译器1.2.1 gcc/g (支持Linux/Windows/MacOSX)1.2.2 clang/clang (支持Linux/Windows/MacOS)1.2.3 Microsoft Visual Studio…...
二维数组与指针【C语言】
二维数组与指针 一维数组一维数组与指针二维数组二维数组与指针总结补充判断以下方式是否正确打印二维数组一维数组 int arr[] = {11, 22, 33, 44};arr:首地址(第一个元素的地址) 一维数组与指针 int arr[] = {11, 22, 33, 44};因为,arr表示的是首地址,等价于 int* p =…...
解决linux下安装apex库报错:ModuleNotFoundError: No module named ‘packaging‘
使用如下命令安装apex: git clone https://github.com/NVIDIA/apex cd apex pip install -v --disable-pip-version-check --no-cache-dir --global-option"--cpp_ext" --global-option"--cuda_ext" ./ 报错: Running command py…...
React基础教程(07):条件渲染
1 条件渲染 使用条件渲染,结合TodoList案例,进行完善,实现以下功能: 当列表中的数据为空的时候,现实提示信息暂无待办事项当列表中存在数据的时候,提示信息消失 这里介绍三种实现方式。 注意这里的Empty是…...
回归预测 | Matlab实现NGO-HKELM北方苍鹰算法优化混合核极限学习机多变量回归预测
回归预测 | Matlab实现NGO-HKELM北方苍鹰算法优化混合核极限学习机多变量回归预测 目录 回归预测 | Matlab实现NGO-HKELM北方苍鹰算法优化混合核极限学习机多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现NGO-HKELM北方苍鹰算法优化混合核极限…...
操作系统——信号
将信号分为以上四个阶段 1.信号注册:是针对信号处理方式的规定,进程收到信号时有三种处理方式:默认动作,忽略,自定义动作。如果不是自定义动作,这一步可以忽略。这个步骤要使用到signal/sigaction接口 2.…...
力扣1482.制作m束花所需的最少时间
力扣1482.制作m束花所需的最少时间 二分答案 check的时候 用一个bool数组判断是否开花找连续的k朵花 const int N 1e510;int st[N];class Solution {public:int minDays(vector<int>& bloomDay, int m, int k) {int n bloomDay.size();if(n < (long long)m*…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
书籍“之“字形打印矩阵(8)0609
题目 给定一个矩阵matrix,按照"之"字形的方式打印这个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为:1,…...
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南 背景介绍完整操作步骤1. 创建Docker容器环境2. 验证GUI显示功能3. 安装ROS Noetic4. 配置环境变量5. 创建ROS节点(小球运动模拟)6. 配置RVIZ默认视图7. 创建启动脚本8. 运行可视化系统效果展示与交互技术解析ROS节点通…...
