erlang:now() 是如何工作的


-module(test_now).
-compile(export_all).
start() ->  
    {_, A, _} = now(),
    loop(0, A).
loop(A) ->  
    {_, B, _} = now(),  
    if   
        B == A + 1 -> loop(0, B);  
        true -> loop(A)  
    end.  
loop(T, B) ->
    {_, C, _} = now(),
    if 
        C == B + 1 -> io:write(T);
        true -> loop(T+1, B)
    end.

从逻辑上讲,此代码应该运行1+秒。但结果返回得很快,远远不到一秒钟。如果我经常在 Eshell 中调用test_now:start()(向上箭头、输入、向上箭头、输入...),结果总是999999ok

从文档(现在/0):

还保证对此 BIF 的后续调用返回 不断增加的价值。因此,从现在()返回值 可用于生成唯一的时间戳,如果在 快速机器上的紧密循环 节点的时间可能会变得偏斜。

因此,您不能像示例中那样使用 now/0 来检查时间。您可以尝试 os:timestamp/0 改为:

start() ->  
    {_, S, MS} = os:timestamp(),
    loop(0, {S, MS}).
loop(T, {S, MS}=Start) ->
    {_, S2, MS2} = os:timestamp(),
    if 
        S2 == S + 1 andalso MS2 == MS -> io:format("~p~n", [T]);
        true -> loop(T + 1, Start)
    end.

例:

1> timer:tc(test_timestamp, start, []).
13600591
{1000047,ok}

但是,如果您只想在一秒钟内收到一些通知,请考虑使用 erlang:send_after/3 或 erlang:start_timer/3:

start() ->  
    erlang:send_after(1000, self(), timeout),
    loop(0).
loop(T) ->
    receive
        timeout -> io:format("~p~n", [T])
    after
        0 -> loop(T + 1)
    end.

例:

1> timer:tc(test_timer, start, []).
27433087
{1000520,ok}

now/0> 如果您想等待 1 秒(即 C == B +1if中),您还必须考虑微秒分量。

在极端情况下now() = {_, X, 999999},这意味着秒分量将在 1 微秒内X+1

我不知道为什么您总是会使用此解决方案获得999999循环。

相关内容

  • 没有找到相关文章

最新更新