You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Erlang多进程/多函数创建进程及ParallelJoin进程异常处理问题

解决Erlang进程管理与ParallelJoin进程问题

1. 多进程/多函数创建与进程链接

在Erlang里,创建进程最常用的是spawn/1、spawn/3(指定模块、函数、参数);如果需要让进程感知对方的退出状态,就用spawn_link/1或spawn_link/3建立进程链接。

举个实际用法例子:

  • 从匿名函数创建独立进程:Pid = spawn(fun() -> taskTwo() end)
  • 从指定模块函数创建并建立链接:spawn_link(model, taskThree, [])

进程链接的核心作用是:当被链接的进程终止时,当前进程会收到EXIT信号(默认会跟着终止,除非开启陷阱EXIT);如果是正常退出,也会向链接进程发送{'EXIT', Pid, normal}消息(需要开启陷阱EXIT才能捕获)。

2. 将系统进程接收的信号转换为消息

要把EXIT信号转换成可处理的消息,你需要在目标进程中设置trap_exit标志,调用process_flag(trap_exit, true)即可。

比如在ParallelJoin进程启动时先执行这个操作:

parallel_join() ->
    process_flag(trap_exit, true), % 开启EXIT陷阱,把系统信号转为可接收的消息
    % 后续消息处理逻辑
    ...

设置后,当链接的进程退出时,ParallelJoin进程就会在消息队列中收到{'EXIT', Pid, Reason}格式的消息,而不是直接被终止,你可以在receive代码块里自定义处理逻辑。

3. 修复ParallelJoin进程,让taskFive正常执行

你提到taskFive未执行,大概率是因为ParallelJoin进程没有正确捕获关联进程的EXIT消息,或者没等到所有关联进程退出就中断了逻辑。下面是完整的可运行代码,解决这个问题:

-module(model).
-compile(export_all).

start() ->
    % 创建ParallelJoin主进程
    ParallelPid = spawn(model, parallel_join, []),
    % 创建三个任务进程并与ParallelJoin建立链接
    spawn_link(model, taskTwo, [ParallelPid]),
    spawn_link(model, taskThree, [ParallelPid]),
    spawn_link(model, taskFour, [ParallelPid]),
    ok.

% 模拟任务进程:执行后正常退出
taskTwo(_Parent) ->
    io:format("Task Two is running~n"),
    timer:sleep(1000),
    exit(normal).

taskThree(_Parent) ->
    io:format("Task Three is running~n"),
    timer:sleep(1500),
    exit(normal).

taskFour(_Parent) ->
    io:format("Task Four is running~n"),
    timer:sleep(2000),
    exit(normal).

% ParallelJoin主进程逻辑
parallel_join() ->
    % 开启EXIT陷阱,接收关联进程的退出消息
    process_flag(trap_exit, true),
    % 等待3个任务进程全部正常退出
    wait_for_tasks(3),
    % 所有任务完成后启动taskFive
    spawn(model, taskFive, []).

% 计数等待任务退出
wait_for_tasks(0) -> ok;
wait_for_tasks(Remaining) ->
    receive
        {'EXIT', _Pid, normal} ->
            io:format("Received normal exit signal from task~n"),
            wait_for_tasks(Remaining - 1);
        % 忽略其他无关消息
        _UnrelatedMsg ->
            wait_for_tasks(Remaining)
    end.

% 最终要执行的taskFive
taskFive() ->
    io:format("Task Five is running! 🎉~n"),
    timer:sleep(1000),
    io:format("Task Five completed successfully~n").

关键修复点:

  • 开启EXIT陷阱:parallel_join/0开头的process_flag(trap_exit, true)是核心,没有它,ParallelJoin进程会在第一个关联进程退出时被直接终止,根本无法走到启动taskFive的步骤。
  • 计数等待所有任务:wait_for_tasks/1函数会一直阻塞等待,直到收到3个正常退出的消息,确保所有关联进程都完成后才启动taskFive。
  • 进程链接:用spawn_link创建taskTwo、taskThree、taskFour,确保它们的退出信号能传递给ParallelJoin进程。

你可以编译运行这个代码验证效果:

c(model).
model:start().

内容的提问来源于stack exchange,提问作者Kiros

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:23:22