2016-08-22 241 views
3

我相信我在某处读过关于热重新加载时使用spawn/1spawn/3的区别,但我无法找到有关该主题的任何完整信息。所以我想知道实际上是否有区别,如果有,那么它是什么?一些例子会很棒。谢谢。spawn/1和spawn/3之间的差异

回答

5

两者的区别在于spawn/1进行本地函数调用,而spawn/3进行“完全限定”函数调用。

当您加载模块的新版本时,旧版本仍然保留,并且旧版本中执行的任何进程都会继续执行此操作。例外情况是,如果进程执行“完全限定”的函数调用,包括模块名称:在这种情况下,始终使用最新版本的代码。

例如,该模块:

defmodule Foo do 

    def start_loop do 
    spawn(fn -> loop end) 
    end 

    def loop do 
    receive do 
     :foo -> 
     spawn &print_foo/0 
     loop 
     :reload -> 
     Foo.loop 
    end 
    end 

    def print_foo do 
    IO.puts "foo 1" 
    end 
end 

我们可以开始一个过程,每次我们发送:foo到它的时候,它产生一个打印foo 1另一个进程:

iex(1)> c("foo.ex") 
[Foo] 
iex(2)> p = Foo.start_loop 
#PID<0.68.0> 
iex(3)> send p, :foo 
foo 1 
:foo 
iex(4)> send p, :foo 
foo 1 
:foo 

现在,如果我们修改模块来代替打印foo 2并重新编译并重新加载它,则不会立即发生变化:

iex(5)> c("foo.ex")  
warning: redefining module Foo (current version loaded from Elixir.Foo.beam) 
    foo.ex:1 

[Foo] 
iex(6)> send p, :foo 
foo 1 
:foo 

当我们告诉只是过程中的“刷新”,通过使该模块的完全合格的号召,做我们得到的新版本:

iex(7)> send p, :reload 
:reload 
iex(8)> send p, :foo 
foo 2 
:foo 

当然,如果你使用spawn/1与一个功能,只是一个完全合格的电话,差异消失:

spawn(fn -> Foo.print_foo end) 
+0

我不能要求更好的解释,谢谢。 – JustMichael