檢視原始碼 timer (stdlib v6.2)
計時器函式。
此模組提供與時間相關的實用函式。除非另有說明,時間一律以毫秒為單位。所有計時器函式都會立即返回,無論另一個處理序是否正在執行工作。
計時器函式的成功評估會給出包含計時器參考值(表示為 TRef
)的回傳值。透過使用 cancel/1
,回傳的參考值可用於取消任何請求的動作。TRef
是一個 Erlang 項,其內容不得變更。
逾時時間並非精確,但至少與請求的時間一樣長。
使用 erlang:send_after/3
和 erlang:start_timer/3
建立計時器比使用此模組提供的計時器更有效率。然而,計時器模組在 OTP 25 中已獲得改進,使其更有效率且較不易過載。請參閱效率指南中的計時器模組章節。
如需 Erlang 中計時器的詳細資訊,請參閱 ERTS 使用者指南的 計時器 章節 Erlang 中的時間與時間校正。
範例
範例 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
是相關計時器函式回傳的唯一計時器參考值。
將帶有原因 Reason1
的結束訊號傳送至 Target
,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)]
,即 1,000 個間隔計時器以 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().
將帶有原因 Reason1
的結束訊號傳送至 Target
,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.
啟動計時器伺服器。
通常,伺服器不需要明確啟動。如果需要,它會動態啟動。這在開發期間很有用,但在目標系統中,伺服器應明確啟動。為此,請使用 Kernel 的組態參數。
等同於 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)
,則會以 TimeUnit
為單位測量 Fun
的執行時間。在 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
是從應用程式傳回的值。