concurrency - Erlang类(class)并发练习: Can my answer be improved?

标签 concurrency erlang

我正在做这个练习来自 erlang.org course :

2) Write a function which starts N processes in a ring, and sends a message M times around all the processes in the ring. After the messages have been sent the processes should terminate gracefully.



这是我想出的:
-module(ring).
-export([start/2, node/2]).

node(NodeNumber, NumberOfNodes) ->
  NextNodeNumber = (NodeNumber + 1) rem NumberOfNodes,
  NextNodeName = node_name(NextNodeNumber),
  receive
    CircuitNumber ->
      io:format("Node ~p Circuit ~p~n", [NodeNumber, CircuitNumber]),
      LastNode = NodeNumber =:= NumberOfNodes - 1,
      NextCircuitNumber = case LastNode of
                           true ->
                             CircuitNumber - 1;
                           false ->
                             CircuitNumber
                         end,
      if
        NextCircuitNumber > 0 ->
          NextNodeName ! NextCircuitNumber;
        true ->
          ok
      end,
      if
        CircuitNumber > 1 ->
          node(NodeNumber, NumberOfNodes);
        true ->
          ok
      end
  end.

start(NumberOfNodes, NumberOfCircuits) ->
  lists:foreach(fun(NodeNumber) ->
                    register(node_name(NodeNumber),
                             spawn(ring, node, [NodeNumber, NumberOfNodes]))
                end,
                lists:seq(0, NumberOfNodes - 1)),
  node_name(0) ! NumberOfCircuits,
  ok.

node_name(NodeNumber) ->
  list_to_atom(lists:flatten(io_lib:format("node~w", [NodeNumber]))).

这是它的输出:
17> ring:start(3, 2).
Node 0 Circuit 2
ok
Node 1 Circuit 2
Node 2 Circuit 2
Node 0 Circuit 1
Node 1 Circuit 1
Node 2 Circuit 1

如果我真的了解 Erlang,我会不会做不同的事情来改进这段代码?特别是:
  • 除了在最后两个 if 语句中指定什么都不做的“true”子句之外,还有其他选择吗?
  • 我真的优雅地终止了吗?结束已注册的进程时是否需要任何特殊操作?
  • 最佳答案

    欢迎来到二郎!我希望你和我一样喜欢它。

    Is there any alternative to specifying a do-nothing "true" clause in the last two if statements?



    你可以把这些关掉。我用这个运行了你的代码:
    if NextCircuitNumber > 0 ->
      NextNodeName ! NextCircuitNumber
    end,
    if CircuitNumber > 1 ->
      node(NodeNumber, NumberOfNodes)
    end
    

    它对我有用。

    Am I indeed terminating gracefully? Is any special action required when ending a process which was registered?



    是的,你是。您可以通过运行 i(). 来验证这一点。命令。这将显示进程列表,如果您注册的进程没有终止,您会看到许多已注册的进程遗留下来,如 node0 , node1等。您也将无法再次运行您的程序,因为尝试注册已注册的名称时会出错。

    至于你可以做的其他事情来改进代码,没有太多,因为你的代码基本上没问题。我可能会做的一件事是不使用 NextNodeName多变的。您可以直接发送消息到node_name(NextNodeNumber)这有效。

    此外,您可能可以做更多的模式匹配来改进事情。例如,我在使用您的代码时所做的一项更改是通过传入最后一个节点的编号 (NumberOfNodes - 1) 来生成进程。 ,而不是通过 NumberOfNodes .然后,我可以在我的 node/2 中进行模式匹配像这样的函数头
    node(LastNode, LastNode) ->
        % Do things specific to the last node, like passing message back to node0
        % and decrementing the CircuitNumber
    node(NodeNumber, LastNode) ->
        % Do things for every other node.
    

    这让我清理了一些 caseif您的 node 中的逻辑功能并使其更整洁。

    希望能帮到你,祝你好运。

    关于concurrency - Erlang类(class)并发练习: Can my answer be improved?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5135229/

    相关文章:

    erlang - Dialyzer 说函数永远不会被调用,即使它是

    erlang - 尾递归与非尾递归。前者慢吗?

    erlang - 使用 Elixir Genstage 的运行时动态计算图

    network-programming - 将 SO_REUSEPORT 与 Phoenix 一起使用

    Java ConcurrentHashMap 损坏的值

    java - Callable 执行期间出现异常

    ios - CoreData 并发(用于与 CloudKit 同步)

    java - 在 ThreadLocal 中包装 JDBC 连接单例

    xcode - XCode 4 支持 Erlang 语法突出显示和代码完成吗?

    c# - 并发调用时可以等待损坏值