非常教程

Elixir 1.5参考手册

处理 | Process

处理 | Process

使用过程和过程字典的方便性。

除了本模块中可用的功能外,Kernel模块公开和自动导入一些与可通过以下函数提供的进程相关的基本功能:

  • Kernel.spawn/1Kernel.spawn/3
  • Kernel.spawn_link/1Kernel.spawn_link/3
  • Kernel.spawn_monitor/1Kernel.spawn_monitor/3
  • Kernel.self/0
  • Kernel.send/2

类型

spawn_opt()spawn_opts()

功能

alive?(pid)

告诉给定进程是否是活动的。

cancel_timer(timer_ref, options \ [])

取消返回的计时器 send_after/3

delete(key)

key从流程字典中删除给定的内容

demonitor(monitor_ref, options \ [])

恶魔监视器通过给定的标识符来识别 reference

exit(pid, reason)

用给定的reasonto 发送一个退出信号pid

flag(flag, value)

设置给定flagvalue用于调用进程

flag(pid, flag, value)

设置给定flagvalue对于给定的过程pid

get()

返回流程字典中的所有键值对。

get(key, default\nil)

返回给定值的值。key在流程字典中,或default如果key未设置

get_keys()

返回流程字典中的所有键。

get_keys(value)

返回进程字典中具有value

group_leader()

返回调用进程的组领导的PID。

group_leader(pid, leader)

设置给定组的组长。pidleader

hibernate(mod, fun_name, args)

将调用进程置于“休眠”状态。

info(pid)

返回有关由pid,或返回nil如果进程没有活动

info(pid, spec)

返回有关由进程标识的进程的信息pid,或返回nil进程没有活动的进程

link(pid_or_port)

创建调用进程和给定项目(进程或端口)之间的链接

list()

返回对应于本地节点上当前存在的所有进程的PID列表。

monitor(item)

开始监视给定的item从调用过程中

put(key, value)

商店给定key- value一对进程字典

read_timer(timer_ref)

读取由...send_after/3创建的计时器

register(pid_or_port, name)

在给定的情况pid_or_port下注册给定的name

registered()

返回已使用register/2

send(dest, msg, options)

向给定进程发送消息。

send_after(dest, msg, time, opts \ [])

发送msg到毫秒desttime

sleep(timeout)

为当前进程安排当前进程 timeout

sleep(timeout)

根据给定的选项生成给定的函数。

spawn(mod, fun, args, opts)

fun从模块中产生给定的函数modargs根据给定的选项传递给定的函数

unlink(pid_or_port)

删除调用进程和给定项目(进程或端口)之间的链接

unregister(name)

移除注册name,与PID或端口标识符关联。

whereis(name)

返回在namenil如果名称未注册

spawn_opt()

spawn_opt ::
  :link |
  :monitor |
  {:priority, :low | :normal | :high} |
  {:fullsweep_after, non_neg_integer} |
  {:min_heap_size, non_neg_integer} |
  {:min_bin_vheap_size, non_neg_integer}

spawn_opts()

spawn_opts() :: [spawn_opt]

alive?(pid)

alive?(pid) :: boolean

指示给定进程是否处于活动状态。

如果标识的进程pid存在(即,它不退出并且还没有退出),则该函数返回true。否则,它返回false

pid必须引用在本地节点上运行的进程。

编译器插入。

cancel_timer(timer_ref, options \ [])

cancel_timer(reference, options) ::
  non_neg_integer |
  false |
  :ok when options: [async: boolean, info: boolean]

取消返回的计时器send_after/3

当结果是整数时,它表示计时器过期前的毫秒时间。

当结果是false,对应于timer_ref找不到。这可能是因为计时器过期了,因为它已经被取消了,或者是因为timer_ref从来不和计时器对应。

即使计时器已经过期并且消息已经发送,此函数也不会告诉您超时消息是否已到达其目的地。

备选方案

  • :async- (boolean)何时false,取消请求是同步的。何时true,取消请求是异步的,意味着取消定时器的请求被发出并立即:ok返回。默认为false
  • :info - (boolean)是否返回有关正在取消的定时器的信息。当:async选择是false:infotrue,则整数或false(如上述)被返回。如果:asyncfalse:infofalse:ok被返回。如果:asynctrue:infotrue,则在执行取消操作时,表单中的消息{:cancel_timer, timer_ref, result}(其中result是整数或false类似于上述内容)会发送给此函数的调用者。如果:asynctrue:infofalse,不发送任何消息。默认为true

编译器插入。

delete(key)

delete(term) :: term | nil

删除给定的key从过程字典。

返回下得值key的进程字典,或者nil如果key没有被存储在进程字典。

实例

Process.put(:comments, ["comment", "other comment"])
Process.delete(:comments)
#=> ["comment", "other comment"]
Process.delete(:comments)
#=> nil

demonitor(monitor_ref, options \ [])

demonitor(reference, options :: [:flush | :info]) :: boolean

恶魔监视器通过给定的标识符来识别reference

如果monitor_ref是调用进程通过调用获得的引用monitor/1,则该监视被关闭。如果监控已关闭,则不会发生任何事情。

查看:erlang.demonitor/2更多信息。

编译器插入。

exit(pid, reason)

exit(pid, term) :: true

用给定的reasonto 发送一个退出信号pid

如果reason除了:normal或以外的任何术语,则以下行为适用:kill

  1. 如果pid不陷阱退出,pid将退出给定reason

2. 如果pid陷阱退出,则退出信号被转换为消息{:EXIT, from, reason}并传递到消息队列中pid

如果reason是原子:normalpid则不会退出(除非pid是调用过程,在这种情况下它将随原因退出:normal)。如果陷入退出,退出信号被转换为消息{:EXIT, from, :normal}并传递到其消息队列。

如果reason是原子:kill,即如果Process.exit(pid, :kill)被调用,则发送无法接收的退出信号,pid其将无条件地退出:killed

编译器插入。

实例

Process.exit(pid, :kill)
#=> true

flag(flag, value)

flag(:trap_exit, boolean) :: boolean
flag(:sensitive, boolean) :: boolean
flag(:save_calls, 0..10000) :: 0..10000
flag(:priority, priority_level) :: priority_level
flag({:monitor_nodes, term}, term) :: term
flag(:monitor_nodes, term) :: term
flag(:min_heap_size, non_neg_integer) :: non_neg_integer
flag(:min_bin_vheap_size, non_neg_integer) :: non_neg_integer
flag(:message_queue_data, :erlang.message_queue_data) :: :erlang.message_queue_data
flag(:max_heap_size, heap_size) :: heap_size
flag(:error_handler, module) :: module

设置给定flagvalue用于呼叫进程。

返回旧的值flag

查看:erlang.process_flag/2更多信息。

需要注意的是flag价值观:max_heap_size:message_queue_data仅可自OTP 19。

编译器插入。

flag(pid, flag, value)

flag(pid, :save_calls, 0..10000) :: 0..10000

设置给定flagvalue对于给定的过程pid

返回旧的值flag

ArgumentError如果pid不是本地进程,则会引发此问题。

允许flag的值只是允许的值的一个子集flag/2,即:save_calls

查看:erlang.process_flag/3更多信息。

编译器插入。

get()

get() :: [{term, term}]

返回流程字典中的所有键值对。

编译器插入。

get(key, default \ nil)

get(term, default :: term) :: term

返回给定值key的过程中字典,或者default如果key未设置。

get_keys()

get_keys() :: [term]

返回流程字典中的所有键。

编译器插入。

get_keys(value)

get_keys(term) :: [term]

返回具有给定值的流程字典中的所有键value

编译器插入。

group_leader()

group_leader() :: pid

返回调用进程的组领导的PID。

编译器插入。

group_leader(pid, leader)

group_leader(pid, leader :: pid) :: true

设置给定的组长pidleader

通常情况下,当从某个shell启动的进程应该具有组长以外的组时,就会使用:init

编译器插入。

hibernate(mod, fun_name, args)

hibernate(module, atom, list) :: no_return

将调用进程置于“休眠”状态。

调用进程处于等待状态,其内存分配尽可能减少,如果进程在不久的将来不会收到任何消息,这将非常有用。

查看:erlang.hibernate/3更多信息。

编译器插入。

info(pid)

info(pid) :: keyword

返回有关由进程标识的进程的信息pid,或返回nil进程没有活动的进程。

仅用于调试信息。

查看:erlang.process_info/1更多信息。

info(pid, spec)

info(pid, atom | [atom]) ::
  {atom, term} |
  [{atom, term}] |
  nil

返回有关由进程标识的进程的信息pid,或返回nil进程没有活动的进程。

查看:erlang.process_info/2更多信息。

info(pid, spec)

link(pid | port) :: true

创建调用进程和给定项目(进程或端口)之间的链接。

链接是双向的。链接的流程可以通过使用取消关联unlink/1

如果这样的链接已经存在,这个函数什么也不做,因为在两个给定的进程之间只能有一个链接。如果一个进程试图创建一个自己的链接,什么都不会发生。

当两个进程链接时,每个进程都会收到来自另一个进程的退出信号(另请参见exit/2)。我们假设pid1pid2链接。如果pid2以其他原因退出:normal(这也是进程完成其工作时使用的退出原因)并且pid1没有陷阱退出(请参阅参考资料flag/2),那么pid1退出时将以相同的原因退出,pid2并转而向所有其他退出信号发出退出信号关联流程。在pid1陷阱出口时的行为描述如下exit/2

查看:erlang.link/1更多信息。

编译器插入。

list()

list() :: [pid]

返回对应于本地节点上当前存在的所有进程的PID列表。

请注意,如果某个进程正在退出,则认为该进程存在但不存在。这意味着对于这样的过程,alive?/1将返回,false但其PID将成为由该函数返回的PID列表的一部分。

查看:erlang.processes/0更多信息。

编译器插入。

monitor(item)

monitor(pid | {reg_name :: atom, node :: atom} | reg_name :: atom) :: reference

开始监视item调用进程中的给定内容。

一旦被监控的进程死亡,将以下列形式向监控进程发送消息:

{:DOWN, ref, :process, object, reason}

其中:

  • ref是此函数返回的监视器引用;
  • objectpid监视的过程(如果监视PID)或{name, node}(如果监视远程或本地名称);
  • reason 是退出原因。

见监测的必要性举个例子。见:erlang.monitor/2想了解更多信息。

编译器插入。

put(key, value)

put(term, term) :: term | nil

商店给定key- value一对进程字典。

此函数的返回值是以前存储在该值下的值key,或者nil如果没有值存储在该值下面key

实例

# Assuming :locale was not set
Process.put(:locale, "en")
#=> nil
Process.put(:locale, "fr")
#=> "en"

read_timer(timer_ref)

read_timer(reference) :: non_neg_integer | false

读取由send_after/3创建的计时器。

当结果是一个整数时,它表示以毫秒为单位的时间,直到定时器到期。

如果结果是false,则timer_ref找不到相应的计时器。这可能是因为定时器过期,因为它已经被取消,或者因为timer_ref从来没有对应过一个定时器。

即使计时器过期并且发送了消息,该功能也不会告诉您超时消息是否已到达目的地。

编译器插入。

register(pid_or_port, name)

register(pid | port, atom) :: true

在给定的情况pid_or_port下注册给定的name

name必须是原子,然后可以在发送消息时使用,而不是PID /端口标识符Kernel.send/2

register/2ArgumentError在下列任何情况下失败:

  • PID/端口在本地不存在,并且是活动的。
  • 该名称已被注册
  • pid_or_port已经根据不同登记name

以下名称是保留的,不能分配给进程或端口:

  • nil
  • false
  • true
  • :undefined

registered()

registered() :: [atom]

返回已使用注册的名称列表register/2

编译器插入。

send(dest, msg, options)

send(dest, msg, [option]) ::
  :ok |
  :noconnect |
  :nosuspend when dest: pid | port | atom | {atom, node}, msg: any, option: :noconnect | :nosuspend

向给定进程发送消息。

备选方案

  • :noconnect- 使用时,如果发送消息需要自动连接到另一个节点,则不发送消息并返回:noconnect
  • :nosuspend- 使用时,如果发送邮件会导致发件人被暂停,则邮件不会发送并返回:nosuspend

否则,消息将被发送并:ok返回。

实例

iex> Process.send({:name, :node_that_does_not_exist}, :hi, [:noconnect])
:noconnect

编译器插入。

send_after(dest, msg, time, opts \ [])

send_after(pid | atom, term, non_neg_integer, [option]) :: reference when option: {:abs, boolean}

发送msg到毫秒desttime

如果dest是PID,它必须是本地进程的PID,无论是死还是活。如果dest是原子,它必须是在交付时查找的注册过程的名称。如果名称不涉及过程,则不会产生错误。

这个函数返回一个定时器引用,它可以被读取read_timer/1或取消cancel_timer/1

如果给定dest的PID不存在或给定的PID退出,定时器将自动取消。请注意,定时器在dest原子时不会自动取消(因为原子分辨率是在交付时完成的)。

编译器插入。

备选方案

  • :abs- (布尔值)时falsetime作为相对于当前时间单调进行处理。当truetime是在该二郎单调时间的绝对值msg应该交付给dest。要阅读更多关于Erlang单调时间和其他与时间有关的概念,请查看System模块的文档。默认为false

实例

timer_ref = Process.send_after(pid, :hi, 1000)

sleep(timeout)

sleep(timeout) :: :ok

为当前进程安排当前进程timeout

timeout是以整数或原子睡眠的毫秒数:infinity。当:infinity给出时,当前进程将永久休眠,而不消耗或回复消息。

谨慎使用此功能。几乎所有sleep/1在Elixir中都会使用的情况下,可能会有更准确,更快,更准确的方式来实现消息传递。

例如,如果您正在等待某个进程执行某些操作,则最好将此类操作的进度与消息进行通信。

换句话说,不要*

Task.start_link fn ->
  do_something()
  ...
end

# Wait until work is done
Process.sleep(2000)

*

parent = self()
Task.start_link fn ->
  do_something()
  send parent, :work_is_done
  ...
end

receive do
  :work_is_done -> :ok
after
  30_000 -> :timeout # Optional timeout
end

像上面这样的案子,Task.async/1Task.await/2都是首选。

同样,如果您正在等待进程终止,则监视该进程而不是休眠。不要*

Task.start_link fn ->
  ...
end

# Wait until task terminates
Process.sleep(2000)

相反*

{:ok, pid} =
  Task.start_link fn ->
    ...
  end

ref = Process.monitor(pid)
receive do
  {:DOWN, ^ref, _, _, _} -> :task_is_down
after
  30_000 -> :timeout # Optional timeout
end

spawn(fun, opts)

spawn((() -> any), spawn_opts) :: pid | {pid, reference}

根据给定的选项生成给定的函数。

结果取决于给定的选项。特别是,如果:monitor作为选项,它将返回一个包含PID和监视引用的元组,否则只返回生成的进程PID。

更多选择可用; 为可用选项检查的综合列表:erlang.spawn_opt/4

编译器插入。

spawn(mod, fun, args, opts)

spawn(module, atom, list, spawn_opts) ::
  pid |
  {pid, reference}

fun从模块中产生给定的函数modargs根据给定的选项传递给定的函数。

结果取决于给定的选项。特别是,如果:monitor作为选项给出,它将返回一个包含PID和监视参考的元组,否则返回派生过程PID。

它也接受额外的选项,查看可用选项列表:erlang.spawn_opt/4

编译器插入。

unlink(pid_or_port)

unlink(pid | port) :: true

删除调用进程和给定项目(进程或端口)之间的链接。

如果没有这样的链接,这个函数什么都不做。如果pid_or_port不存在,这个函数不会产生任何错误,而且什么也不做。

这个函数的返回值总是true

查看:erlang.unlink/1更多信息。

编译器插入。

unregister(name)

unregister(atom) :: true

删除已注册的name,与PID或端口标识符关联的。

失败ArgumentError如果名称未注册到任何PID或端口。

编译器插入。

whereis(name)

whereis(atom) :: pid | port | nil

返回根据namenil名称未注册注册的PID或端口标识符。

查看:erlang.whereis/1更多信息。

处理 | Process相关

Elixir 1.5

Elixir 基于 Erlang 虚拟机的函数式、面向并行,是一种较好的编程语言。它以 Erlang 为基础,支持分布式、高容错、实时应用程序的开发。

主页 https://elixir-lang.org/
源码 https://github.com/elixir-lang/elixir
版本 1.5
发布版本 1.5.2