tldr;这里的简短回答是,如果您想保留排序,工作人员需要知道他们正在处理的元素的索引并将其返回给调用者,以便重新组合列表
我建议将项目的索引发送给每个工人(例如F(Element, Index))。然后,不仅仅是将结果发回,而是发送结果和索引 ({Index, Result}),这样当您从每个工作人员那里获得结果时,您就知道它在列表中的位置。然后使用选择性接收将它们按顺序放回:
results_from_workers(Max) ->
results_from_workers(Max, 0, []).
results_from_workers(Max, Num, NewList) when Num > Max ->
% If the next number is greater than the max, reverse the list and return it
lists:reverse(NewList);
results_from_workers(Max, Num, NewList) ->
% Receive the result for the next number
receive
{Num, Result} ->
results_from_workers(Num + 1, [Result|NewList])
end.
% Then call your code that starts the workers
sender(List,F),
% Then call `results_from_workers/1` with the length of the list being processed, it should return the new list
NewList = results_from_workers(length(List)).
这样做的缺点是,如果进程崩溃,results_from_workers 进程将挂起,等待崩溃进程的结果。您应该将您的工作进程链接到启动它们的进程,所以这应该不是问题。如果由于某种原因您不能或不想链接到工作进程,您可以在接收中使用after Timeout -> failed 子句,Timeout 是一个整数,以毫秒为单位表示超时。请注意,如果您的工作人员花费的时间比预期的要长,则可能会执行超时子句,而您没有结果。