Elixir进程基础 #
一、进程概念 #
1.1 什么是进程 #
Elixir进程是轻量级的并发单元,不是操作系统进程。它们:
- 非常轻量(约2KB初始内存)
- 创建和销毁成本低
- 可以同时运行数百万个
- 通过消息传递通信
1.2 进程与操作系统进程 #
| 特性 | Elixir进程 | OS进程 |
|---|---|---|
| 内存 | ~2KB | ~MB |
| 创建成本 | 极低 | 高 |
| 数量 | 百万级 | 数百 |
| 通信 | 消息传递 | IPC |
二、创建进程 #
2.1 spawn #
elixir
iex(1)> pid = spawn(fn -> IO.puts("Hello from process!") end)
Hello from process!
#PID<0.123.0>
2.2 spawn_link #
创建并链接进程(一个崩溃会影响另一个):
elixir
iex(1)> spawn_link(fn -> raise "Error!" end)
** (RuntimeError) Error!
2.3 spawn_monitor #
创建并监控进程:
elixir
iex(1)> {pid, ref} = spawn_monitor(fn -> raise "Error!" end)
{#PID<0.123.0>, #Reference<0.1234567890.1234567890.123456>}
iex(2)> flush()
{:DOWN, #Reference<0.1234567890.1234567890.123456>, :process, #PID<0.123.0>,
%RuntimeError{message: "Error!"}}
:ok
2.4 self #
获取当前进程PID:
elixir
iex(1)> self()
#PID<0.1.0>
三、消息传递 #
3.1 发送消息 #
elixir
iex(1)> pid = spawn(fn ->
...> receive do
...> msg -> IO.puts("Received: #{inspect(msg)}")
...> end
...> end)
#PID<0.123.0>
iex(2)> send(pid, :hello)
Received: :hello
:hello
3.2 接收消息 #
elixir
iex(1)> receive do
...> {:ok, data} -> "Success: #{data}"
...> {:error, reason} -> "Error: #{reason}"
...> after
...> 1000 -> "Timeout"
...> end
3.3 消息队列 #
每个进程都有消息队列:
elixir
iex(1)> self() |> Process.info(:messages)
{:messages, []}
iex(2)> send(self(), :hello)
:hello
iex(3)> self() |> Process.info(:messages)
{:messages, [:hello]}
四、进程通信模式 #
4.1 请求-响应 #
elixir
defmodule Echo do
def start do
spawn(fn -> loop() end)
end
defp loop do
receive do
{from, msg} ->
send(from, {:echo, msg})
loop()
end
end
def echo(pid, msg) do
send(pid, {self(), msg})
receive do
{:echo, response} -> response
after
1000 -> {:error, :timeout}
end
end
end
pid = Echo.start()
Echo.echo(pid, "Hello")
4.2 状态保持进程 #
elixir
defmodule Counter do
def start(initial \\ 0) do
spawn(fn -> loop(initial) end)
end
defp loop(count) do
receive do
{:increment, from} ->
new_count = count + 1
send(from, {:ok, new_count})
loop(new_count)
{:decrement, from} ->
new_count = count - 1
send(from, {:ok, new_count})
loop(new_count)
{:get, from} ->
send(from, {:ok, count})
loop(count)
end
end
def increment(pid) do
send(pid, {:increment, self()})
receive do
{:ok, count} -> count
end
end
def decrement(pid) do
send(pid, {:decrement, self()})
receive do
{:ok, count} -> count
end
end
def get(pid) do
send(pid, {:get, self()})
receive do
{:ok, count} -> count
end
end
end
4.3 广播 #
elixir
defmodule Broadcaster do
def broadcast(pids, msg) do
Enum.each(pids, fn pid -> send(pid, msg) end)
end
end
五、进程链接 #
5.1 link #
elixir
iex(1)> pid = spawn(fn ->
...> receive do
...> _ -> raise "Error!"
...> end
...> end)
#PID<0.123.0>
iex(2)> Process.link(pid)
true
iex(3)> send(pid, :trigger)
** (RuntimeError) Error!
5.2 unlink #
elixir
iex(1)> Process.unlink(pid)
true
5.3 进程标志 #
elixir
iex(1)> Process.flag(:trap_exit, true)
false
iex(2)> spawn_link(fn -> raise "Error!" end)
#PID<0.123.0>
iex(3)> flush()
{:EXIT, #PID<0.123.0>, %RuntimeError{message: "Error!"}}
:ok
六、进程监控 #
6.1 monitor #
elixir
iex(1)> pid = spawn(fn ->
...> receive do
...> _ -> :ok
...> end
...> end)
#PID<0.123.0>
iex(2)> ref = Process.monitor(pid)
#Reference<0.1234567890.1234567890.123456>
iex(3)> send(pid, :stop)
:stop
iex(4)> flush()
{:DOWN, #Reference<0.1234567890.1234567890.123456>, :process, #PID<0.123.0>, :normal}
:ok
6.2 demonitor #
elixir
iex(1)> Process.demonitor(ref)
true
6.3 链接与监控的区别 #
| 特性 | link | monitor |
|---|---|---|
| 方向 | 双向 | 单向 |
| 崩溃传播 | 是 | 否 |
| 多次监控 | 否 | 是 |
| 用途 | 监督树 | 监控 |
七、进程信息 #
7.1 Process.info #
elixir
iex(1)> pid = self()
#PID<0.1.0>
iex(2)> Process.info(pid, :status)
{:status, :running}
iex(3)> Process.info(pid, :message_queue_len)
{:message_queue_len, 0}
iex(4)> Process.info(pid, [:status, :message_queue_len])
[status: :running, message_queue_len: 0]
7.2 进程状态 #
:running- 正在运行:waiting- 等待消息:runnable- 可运行:suspended- 挂起
7.3 进程列表 #
elixir
iex(1)> Process.list()
[#PID<0.1.0>, #PID<0.2.0>, ...]
八、进程注册 #
8.1 注册名称 #
elixir
iex(1)> pid = spawn(fn -> loop() end)
#PID<0.123.0>
iex(2)> Process.register(pid, :my_process)
true
iex(3)> send(:my_process, :hello)
:hello
8.2 查找注册进程 #
elixir
iex(1)> Process.whereis(:my_process)
#PID<0.123.0>
iex(2)> Process.registered()
[:my_process, :kernel, ...]
8.3 取消注册 #
elixir
iex(1)> Process.unregister(:my_process)
true
九、进程优先级 #
elixir
iex(1)> Process.flag(:priority, :high)
:normal
优先级:
:low:normal:high:max
十、总结 #
本章学习了:
| 函数 | 用途 |
|---|---|
spawn/1 |
创建进程 |
spawn_link/1 |
创建并链接进程 |
spawn_monitor/1 |
创建并监控进程 |
send/2 |
发送消息 |
receive/1 |
接收消息 |
self/0 |
获取当前PID |
Process.link/1 |
链接进程 |
Process.monitor/1 |
监控进程 |
Process.register/2 |
注册进程名 |
准备好学习进程通信了吗?让我们进入下一章。
最后更新:2026-03-27