查看源代码 timer (stdlib v6.2)
定时器函数。
此模块提供与时间相关的实用函数。除非另有说明,时间始终以毫秒为单位进行度量。所有定时器函数都会立即返回,而无需考虑其他进程完成的工作。
成功执行定时器函数会返回包含定时器引用(表示为 TRef
)的值。通过使用cancel/1
,返回的引用可用于取消任何请求的操作。TRef
是一个 Erlang 术语,其内容不得更改。
超时时间不是精确的,但至少与请求的时间一样长。
使用 erlang:send_after/3
和 erlang: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/2
、apply_interval/3
、apply_interval/4
、apply_repeatedly/2
、apply_repeatedly/3
、apply_repeatedly/4
、send_interval/2
和 send_interval/3
,会链接到定时器执行其任务的进程。
单次定时器,即通过计算以下任何函数创建的定时器:apply_after/2
、apply_after/3
、apply_after/4
、send_after/2
、send_after/3
、exit_after/2
、exit_after/3
、kill_after/1
和 kill_after/2
,不会链接到任何进程。因此,此类定时器仅在达到其超时时间时删除,或者如果通过调用 cancel/1
显式删除时才会被删除。
提供给 apply_after/2
、apply_after/3
、apply_interval/2
、apply_interval/3
、apply_repeatedly/2
和 apply_repeatedly/3
的函数,或由提供给 apply_after/4
、apply_interval/4
和 apply_repeatedly/4
的 Module
、Function
和 Arguments
表示的函数,会在新生成的进程中执行,因此在这些函数中调用 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
(以微秒为单位),其中 T1
和 T2
是与 erlang:timestamp/0
或 os:timestamp/0
返回的格式相同的时标元组。
返回 Seconds
中的毫秒数。
在 Time
毫秒后计算 Destination ! Message
。
在 Time
毫秒后重复计算 Destination ! Message
。
使调用此函数的进程暂停 Time
毫秒,然后返回 ok
,如果 Time
是原子 infinity
,则永远暂停该进程。当然,此函数不会立即返回。
启动定时器服务器。
测量 Fun
的执行时间。
测量 Fun
或 apply(Module, Function, Arguments)
的执行时间。
类型
-type time() :: non_neg_integer().
以毫秒为单位的时间。
-opaque tref()
定时器引用。
函数
-spec apply_after(Time, Function) -> {ok, TRef} | {error, Reason} when Time :: time(), Function :: fun(() -> _), TRef :: tref(), Reason :: term().
在 Time
毫秒后计算 spawn(erlang, apply, [Function, []])
。
-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])
。
-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)
。
-spec apply_interval(Time, Function) -> {ok, TRef} | {error, Reason} when Time :: time(), Function :: fun(() -> _), TRef :: tref(), Reason :: term().
以 Time
为间隔重复计算 spawn(erlang, apply, [Function, []])
,而不考虑先前生成的进程是否已完成。
-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])
,而不考虑先前生成的进程是否已完成。
-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 个进程,远远超过使用默认设置启动的节点所允许的数量(请参阅效率指南中的系统限制部分)。
-spec apply_repeatedly(Time, Function) -> {ok, TRef} | {error, Reason} when Time :: time(), Function :: fun(() -> _), TRef :: tref(), Reason :: term().
以 Time
为间隔重复计算 spawn(erlang, apply, [Function, []])
,等待生成的进程完成,然后再启动下一个。
-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])
,等待生成的进程完成,然后再启动下一个。
-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
,则接下来的两个应用将按顺序立即一个接一个地执行。
取消先前请求的超时。TRef
是相关定时器函数返回的唯一定时器引用。
当 TRef
不是定时器引用时,返回 {ok, cancel}
或 {error, Reason}
。
-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
可以是本地进程标识符或已注册名称的原子。
-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 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
(以微秒为单位),其中 T1
和 T2
是与 erlang:timestamp/0
或 os:timestamp/0
返回的格式相同的时标元组。
-spec seconds(Seconds) -> MilliSeconds when Seconds :: non_neg_integer(), MilliSeconds :: non_neg_integer().
返回 Seconds
中的毫秒数。
-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}
。
另请参阅效率指南中的定时器模块部分。
-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, microsecond)
。
-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)
,则测量 Fun
在 TimeUnit
中的执行时间。在 OTP 26.0 中添加。
-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().
测量 Fun
或 apply(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 中添加
-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
是应用返回的值。