查看源代码 timer (stdlib v6.2)

定时器函数。

此模块提供与时间相关的实用函数。除非另有说明,时间始终以毫秒为单位进行度量。所有定时器函数都会立即返回,而无需考虑其他进程完成的工作。

成功执行定时器函数会返回包含定时器引用(表示为 TRef)的值。通过使用cancel/1,返回的引用可用于取消任何请求的操作。TRef 是一个 Erlang 术语,其内容不得更改。

超时时间不是精确的,但至少与请求的时间一样长。

使用 erlang:send_after/3erlang:start_timer/3 创建定时器比使用此模块提供的定时器更有效。但是,定时器模块在 OTP 25 中得到了改进,使其更加高效且不易过载。请参阅效率指南中的定时器模块部分

有关 Erlang 中定时器的更多信息,请参阅定时器部分,位于Erlang 中的时间和时间校正 ERTS 用户指南中。

示例

示例 1

以下示例展示如何在 5 秒后打印 “Hello World!”

1> timer:apply_after(5000, io, format, ["~nHello World!~n", []]).
{ok,TRef}
Hello World!

示例 2

以下示例展示了一个进程执行某个操作,如果此操作未在限定时间内完成,则会终止该进程

Pid = spawn(mod, fun, [foo, bar]),
%% If pid is not finished in 10 seconds, kill him
{ok, R} = timer:kill_after(timer:seconds(10), Pid),
...
%% We change our mind...
timer:cancel(R),
...

说明

始终可以通过调用 cancel/1 来移除定时器。

间隔定时器,即通过计算以下任何函数创建的定时器:apply_interval/2apply_interval/3apply_interval/4apply_repeatedly/2apply_repeatedly/3apply_repeatedly/4send_interval/2send_interval/3,会链接到定时器执行其任务的进程。

单次定时器,即通过计算以下任何函数创建的定时器:apply_after/2apply_after/3apply_after/4send_after/2send_after/3exit_after/2exit_after/3kill_after/1kill_after/2,不会链接到任何进程。因此,此类定时器仅在达到其超时时间时删除,或者如果通过调用 cancel/1 显式删除时才会被删除。

提供给 apply_after/2apply_after/3apply_interval/2apply_interval/3apply_repeatedly/2apply_repeatedly/3 的函数,或由提供给 apply_after/4apply_interval/4apply_repeatedly/4ModuleFunctionArguments 表示的函数,会在新生成的进程中执行,因此在这些函数中调用 self/0 会返回此进程的 Pid,它与调用 timer:apply_* 的进程不同。

示例

在以下示例中,目的是设置一个定时器,以便在 1 秒后执行一个函数,该函数执行一个虚构的任务,然后希望通过向设置定时器的进程发送 done 消息来通知其完成。

在定时函数内部使用 self/0,以下代码无法按预期工作。任务已完成,但 done 消息被发送到错误的进程并丢失了。

1> timer:apply_after(1000, fun() -> do_something(), self() ! done end).
{ok,TRef}
2> receive done -> done after 5000 -> timeout end.
%% ... 5s pass...
timeout

以下代码在设置定时器的进程中调用 self/0 并将其分配给一个变量,然后在函数中使用该变量将 done 消息发送到该进程,从而按预期工作。

1> Target = self()
<0.82.0>
2> timer:apply_after(1000, fun() -> do_something(), Target ! done end).
{ok,TRef}
3> receive done -> done after 5000 -> timeout end.
%% ... 1s passes...
done

另一种选择是将消息目标作为参数传递给该函数。

1> timer:apply_after(1000, fun(Target) -> do_something(), Target ! done end, [self()]).
{ok,TRef}
2> receive done -> done after 5000 -> timeout end.
%% ... 1s passes...
done

摘要

类型

以毫秒为单位的时间。

定时器引用。

函数

Time 为间隔重复计算 spawn(erlang, apply, [Function, []]),而不考虑先前生成的进程是否已完成。

Time 为间隔重复计算 spawn(erlang, apply, [Function, Arguments]),而不考虑先前生成的进程是否已完成。

Time 为间隔重复计算 spawn(Module, Function, Arguments),而不考虑先前生成的进程是否已完成。

Time 为间隔重复计算 spawn(erlang, apply, [Function, []]),等待生成的进程完成,然后再启动下一个。

Time 为间隔重复计算 spawn(erlang, apply, [Function, Arguments]),等待生成的进程完成,然后再启动下一个。

Time 为间隔重复计算 spawn(Module, Function, Arguments),等待生成的进程完成,然后再启动下一个。

取消先前请求的超时。TRef 是相关定时器函数返回的唯一定时器引用。

Target 发送带有原因 Reason1 的退出信号,Target 可以是本地进程标识符或已注册名称的原子。

返回 Hours + Minutes + Seconds 中的毫秒数。

返回 Hours 中的毫秒数。

返回 Minutes 中的毫秒数。

计算时间差 Tdiff = T2 - T1(以微秒为单位),其中 T1T2 是与 erlang:timestamp/0os:timestamp/0 返回的格式相同的时标元组。

返回 Seconds 中的毫秒数。

Time 毫秒后计算 Destination ! Message

Time 毫秒后重复计算 Destination ! Message

使调用此函数的进程暂停 Time 毫秒,然后返回 ok,如果 Time 是原子 infinity,则永远暂停该进程。当然,此函数不会立即返回。

启动定时器服务器。

测量 Fun 的执行时间。

测量 Funapply(Module, Function, Arguments) 的执行时间。

类型

-type time() :: non_neg_integer().

以毫秒为单位的时间。

-opaque tref()

定时器引用。

函数

链接到此函数

apply_after(Time, Function)

查看源代码 (自 OTP 27.0 起)
-spec apply_after(Time, Function) -> {ok, TRef} | {error, Reason}
                     when Time :: time(), Function :: fun(() -> _), TRef :: tref(), Reason :: term().

Time 毫秒后计算 spawn(erlang, apply, [Function, []])

链接到此函数

apply_after(Time, Function, Arguments)

查看源代码 (自 OTP 27.0 起)
-spec apply_after(Time, Function, Arguments) -> {ok, TRef} | {error, Reason}
                     when
                         Time :: time(),
                         Function :: fun((...) -> _),
                         Arguments :: [term()],
                         TRef :: tref(),
                         Reason :: term().

Time 毫秒后计算 spawn(erlang, apply, [Function, Arguments])

链接到此函数

apply_after(Time, Module, Function, Arguments)

查看源代码
-spec apply_after(Time, Module, Function, Arguments) -> {ok, TRef} | {error, Reason}
                     when
                         Time :: time(),
                         Module :: module(),
                         Function :: atom(),
                         Arguments :: [term()],
                         TRef :: tref(),
                         Reason :: term().

Time 毫秒后计算 spawn(Module, Function, Arguments)

链接到此函数

apply_interval(Time, Function)

查看源代码 (自 OTP 27.0 起)
-spec apply_interval(Time, Function) -> {ok, TRef} | {error, Reason}
                        when Time :: time(), Function :: fun(() -> _), TRef :: tref(), Reason :: term().

Time 为间隔重复计算 spawn(erlang, apply, [Function, []]),而不考虑先前生成的进程是否已完成。

链接到此函数

apply_interval(Time, Function, Arguments)

查看源代码 (自 OTP 27.0 起)
-spec apply_interval(Time, Function, Arguments) -> {ok, TRef} | {error, Reason}
                        when
                            Time :: time(),
                            Function :: fun((...) -> _),
                            Arguments :: [term()],
                            TRef :: tref(),
                            Reason :: term().

Time 为间隔重复计算 spawn(erlang, apply, [Function, Arguments]),而不考虑先前生成的进程是否已完成。

链接到此函数

apply_interval(Time, Module, Function, Arguments)

查看源代码
-spec apply_interval(Time, Module, Function, Arguments) -> {ok, TRef} | {error, Reason}
                        when
                            Time :: time(),
                            Module :: module(),
                            Function :: atom(),
                            Arguments :: [term()],
                            TRef :: tref(),
                            Reason :: term().

Time 为间隔重复计算 spawn(Module, Function, Arguments),而不考虑先前生成的进程是否已完成。

警告

如果衍生进程的执行时间平均大于给定的 Time,则会同时运行多个此类进程。如果执行时间长、间隔短且运行的间隔定时器很多,甚至可能导致超出允许的进程数量。一个极端的例子是 [timer:apply_interval(1, timer, sleep, [1000]) || _ <- lists:seq(1, 1000)],即 1000 个间隔定时器执行一个需要 1 秒才能完成的进程,以 1 毫秒的间隔启动,这将导致同时运行 1,000,000 个进程,远远超过使用默认设置启动的节点所允许的数量(请参阅效率指南中的系统限制部分)。

链接到此函数

apply_repeatedly(Time, Function)

查看源代码 (自 OTP 27.0 起)
-spec apply_repeatedly(Time, Function) -> {ok, TRef} | {error, Reason}
                          when
                              Time :: time(), Function :: fun(() -> _), TRef :: tref(), Reason :: term().

Time 为间隔重复计算 spawn(erlang, apply, [Function, []]),等待生成的进程完成,然后再启动下一个。

链接到此函数

apply_repeatedly(Time, Function, Arguments)

查看源代码 (自 OTP 27.0 起)
-spec apply_repeatedly(Time, Function, Arguments) -> {ok, TRef} | {error, Reason}
                          when
                              Time :: time(),
                              Function :: fun((...) -> _),
                              Arguments :: [term()],
                              TRef :: tref(),
                              Reason :: term().

Time 为间隔重复计算 spawn(erlang, apply, [Function, Arguments]),等待生成的进程完成,然后再启动下一个。

链接到此函数

apply_repeatedly(Time, Module, Function, Arguments)

查看源代码 (自 OTP 26.0 起)
-spec apply_repeatedly(Time, Module, Function, Arguments) -> {ok, TRef} | {error, Reason}
                          when
                              Time :: time(),
                              Module :: module(),
                              Function :: atom(),
                              Arguments :: [term()],
                              TRef :: tref(),
                              Reason :: term().

Time 为间隔重复计算 spawn(Module, Function, Arguments),等待生成的进程完成,然后再启动下一个。

如果衍生进程的执行时间大于给定的 Time,则当前正在运行的进程结束后,将立即衍生下一个进程。假设执行应用的衍生进程的平均执行时间小于 Time,即使某些单独的执行时间大于 Time,在很长一段时间内执行的应用数量也将相同。系统将尽快尝试赶上。例如,如果一个应用需要 2.5*Time,则接下来的两个应用将按顺序立即一个接一个地执行。

-spec cancel(TRef) -> {ok, cancel} | {error, Reason} when TRef :: tref(), Reason :: term().

取消先前请求的超时。TRef 是相关定时器函数返回的唯一定时器引用。

TRef 不是定时器引用时,返回 {ok, cancel}{error, Reason}

链接到此函数

exit_after(Time, Reason1)

查看源代码
-spec exit_after(Time, Reason1) -> {ok, TRef} | {error, Reason2}
                    when Time :: time(), TRef :: tref(), Reason1 :: term(), Reason2 :: term().

等效于 exit_after(Time, self(), Reason)

链接到此函数

exit_after(Time, Target, Reason1)

查看源代码
-spec exit_after(Time, Target, Reason1) -> {ok, TRef} | {error, Reason2}
                    when
                        Time :: time(),
                        Target :: pid() | (RegName :: atom()),
                        TRef :: tref(),
                        Reason1 :: term(),
                        Reason2 :: term().

Target 发送带有原因 Reason1 的退出信号,Target 可以是本地进程标识符或已注册名称的原子。

链接到此函数

hms(Hours, Minutes, Seconds)

查看源代码
-spec hms(Hours, Minutes, Seconds) -> MilliSeconds
             when
                 Hours :: non_neg_integer(),
                 Minutes :: non_neg_integer(),
                 Seconds :: non_neg_integer(),
                 MilliSeconds :: non_neg_integer().

返回 Hours + Minutes + Seconds 中的毫秒数。

-spec hours(Hours) -> MilliSeconds when Hours :: non_neg_integer(), MilliSeconds :: non_neg_integer().

返回 Hours 中的毫秒数。

-spec kill_after(Time) -> {ok, TRef} | {error, Reason2}
                    when Time :: time(), TRef :: tref(), Reason2 :: term().

等效于 exit_after(Time, self(), kill)

链接到此函数

kill_after(Time, Target)

查看源代码
-spec kill_after(Time, Target) -> {ok, TRef} | {error, Reason2}
                    when
                        Time :: time(),
                        Target :: pid() | (RegName :: atom()),
                        TRef :: tref(),
                        Reason2 :: term().

等效于 exit_after(Time, Target, kill)

-spec minutes(Minutes) -> MilliSeconds
                 when Minutes :: non_neg_integer(), MilliSeconds :: non_neg_integer().

返回 Minutes 中的毫秒数。

-spec now_diff(T2, T1) -> Tdiff
                  when T1 :: erlang:timestamp(), T2 :: erlang:timestamp(), Tdiff :: integer().

计算时间差 Tdiff = T2 - T1(以微秒为单位),其中 T1T2 是与 erlang:timestamp/0os:timestamp/0 返回的格式相同的时标元组。

-spec seconds(Seconds) -> MilliSeconds
                 when Seconds :: non_neg_integer(), MilliSeconds :: non_neg_integer().

返回 Seconds 中的毫秒数。

链接到此函数

send_after(Time, Message)

查看源代码
-spec send_after(Time, Message) -> {ok, TRef} | {error, Reason}
                    when Time :: time(), Message :: term(), TRef :: tref(), Reason :: term().

等效于 send_after(Time, self(), Message)

链接到此函数

send_after(Time, Destination, Message)

查看源代码
-spec send_after(Time, Destination, Message) -> {ok, TRef} | {error, Reason}
                    when
                        Time :: time(),
                        Destination :: pid() | (RegName :: atom()) | {RegName :: atom(), Node :: node()},
                        Message :: term(),
                        TRef :: tref(),
                        Reason :: term().

Time 毫秒后计算 Destination ! Message

Destination 可以是远程或本地进程标识符、注册名称的原子或另一个节点上注册名称的元组 {RegName, Node}

另请参阅效率指南中的定时器模块部分

链接到此函数

send_interval(Time, Message)

查看源代码
-spec send_interval(Time, Message) -> {ok, TRef} | {error, Reason}
                       when Time :: time(), Message :: term(), TRef :: tref(), Reason :: term().

等效于 send_interval(Time, self(), Message)

链接到此函数

send_interval(Time, Destination, Message)

查看源代码
-spec send_interval(Time, Destination, Message) -> {ok, TRef} | {error, Reason}
                       when
                           Time :: time(),
                           Destination ::
                               pid() | (RegName :: atom()) | {RegName :: atom(), Node :: node()},
                           Message :: term(),
                           TRef :: tref(),
                           Reason :: term().

Time 毫秒后重复计算 Destination ! Message

Destination 可以是远程或本地进程标识符、注册名称的原子或另一个节点上注册名称的元组 {RegName, Node}

-spec sleep(Time) -> ok when Time :: timeout().

使调用此函数的进程暂停 Time 毫秒,然后返回 ok,如果 Time 是原子 infinity,则永远暂停该进程。当然,此函数不会立即返回。

注意

在 OTP 25 之前,timer:sleep/1 不接受大于 16#ffffffff 的整数超时值,即 2^32-1。自 OTP 25 起,接受任意高的整数值。

-spec start() -> ok.

启动定时器服务器。

通常,服务器不需要显式启动。如果需要,它会动态启动。这在开发过程中很有用,但在目标系统中,服务器需要显式启动。请为此使用内核的配置参数。

链接到此函数

tc(Fun)

查看源代码 (自 OTP R14B03 起)
-spec tc(Fun) -> {Time, Value} when Fun :: function(), Time :: integer(), Value :: term().

等效于 tc(Fun, microsecond)

链接到此函数

tc(Fun, ArgumentsOrTimeUnit)

查看源代码 (自 OTP R14B 起)
-spec tc(Fun, Arguments) -> {Time, Value}
            when Fun :: function(), Arguments :: [term()], Time :: integer(), Value :: term();
        (Fun, TimeUnit) -> {Time, Value}
            when Fun :: function(), TimeUnit :: erlang:time_unit(), Time :: integer(), Value :: term().

测量 Fun 的执行时间。

如果调用为 tc(Fun, Arguments),则等效于 tc(Fun, Arguments, microsecond)

如果调用为 tc(Fun, TimeUnit),则测量 FunTimeUnit 中的执行时间。在 OTP 26.0 中添加。

链接到此函数

tc(ModuleOrFun, FunctionOrArguments, ArgumentsOrTimeUnit)

查看源代码
-spec tc(Module, Function, Arguments) -> {Time, Value}
            when
                Module :: module(),
                Function :: atom(),
                Arguments :: [term()],
                Time :: integer(),
                Value :: term();
        (Fun, Arguments, TimeUnit) -> {Time, Value}
            when
                Fun :: function(),
                Arguments :: [term()],
                TimeUnit :: erlang:time_unit(),
                Time :: integer(),
                Value :: term().

测量 Funapply(Module, Function, Arguments) 的执行时间。

如果调用为 tc(Module, Function, Arguments),则等效于 tc(Module, Function, Arguments, microsecond)

如果调用为 tc(Fun, Arguments, TimeUnit),则等效于 tc(erlang, apply, [Fun, Arguments], TimeUnit)。在 OTP 26.0 中添加

链接到此函数

tc(Module, Function, Arguments, TimeUnit)

查看源代码 (自 OTP 26.0 起)
-spec tc(Module, Function, Arguments, TimeUnit) -> {Time, Value}
            when
                Module :: module(),
                Function :: atom(),
                Arguments :: [term()],
                TimeUnit :: erlang:time_unit(),
                Time :: integer(),
                Value :: term().

计算 apply(Module, Function, Arguments),并测量由 erlang:monotonic_time/0 报告的已用实际时间。

返回 {Time, Value},其中 Time 是以指定的 TimeUnit 为单位的经过的实际时间,而 Value 是应用返回的值。