PHP的Ev教程三(Periodic watcher)

Object發表於2019-02-16

Periodic watcher operation modes (週期性觀察者的執行模式)

根據偏移、間隔和重新排程引數,不同週期的觀察者工作

offset

絕對定時器。在此模式中,interval = 0reschedule_cb = NULL. 這一次只是簡單的觸發在時鐘時間偏移,不重複。當時間跳躍發生時,它不會調整,也就是說,如果它在2014/01/01執行,那麼當系統時間達到或超過這個時間時,它將執行。

程式碼

<?php
echo "start : " . time() . PHP_EOL;
//interval = 0 and reschedule_cb = NULL  在絕對的時間點上執行 如果offset<=當前時間會立即執行
$w1 = new EvPeriodic(time() + 10, 0.0, NULL, function ($w, $revents) {
    echo "w1: enter:", time(), PHP_EOL;
    sleep(5);
    echo "w1: end:", time(), PHP_EOL;
});

//interval = 0 and reschedule_cb = NULL  不收其他timer的影響,還是在絕對的時間點上執行 如果offset<=當前時間會立即執行
$w11 = new EvPeriodic(time() + 20, 0.0, NULL, function ($w, $revents) {
    echo "w11: enter:", time(), PHP_EOL;
});
?>

執行結果

start : 1529568868
w1: enter:1529568877
w1: end:1529568882
w11: enter:1529568888


# 如果我們吧offset都改成改成當前時間 再執行結果
start : 1529568995
w11: enter:1529568995
w1: enter:1529568995
w1: end:1529569000

interval

重複間隔定時器。在這種模式offset = 0reschedule_cb = NULL; 觀察者將總是被安排在下一個偏移量offset + N * interval time(N代表某個整數)超時,然後重複,不管任何時間跳躍。

這並不意味著觸發器之間總是有3600秒的時間,但只有當系統時間顯示一個完整的小時(UTC)時才會呼叫回撥。

這可以用來建立不隨系統時間漂移的定時器:

程式碼

<?php

//offset = 0 and reschedule_cb = NULL 間隔執行,當然如果執行體時間過長,間隔會被延遲
$w2 = new EvPeriodic(0.0, 2.0, NULL, function ($w, $revents) {
    echo "w2:enter:", time(), PHP_EOL;
//    sleep(3);
    echo "w2:end:", time(), PHP_EOL;
});

//offset = 0 and reschedule_cb = NULL 間隔執行,當然如果執行體時間過長,間隔會被延遲,且多個觀察者會互相影響間隔時間
$w3 = new EvPeriodic(0.0, 2.0, NULL, function ($w, $revents) {
    echo "w3:enter:", time(), PHP_EOL;
    // sleep(3);
    echo "w3:end:", time(), PHP_EOL;
});

Ev::run();

執行結果

w2:enter:1529569458
w2:end:1529569458
w3:enter:1529569458
w3:end:1529569458
w3:enter:1529569460
w3:end:1529569460
w2:enter:1529569460
w2:end:1529569460
w2:enter:1529569462
w2:end:1529569462
w3:enter:1529569462
w3:end:1529569462
w3:enter:1529569464
w3:end:1529569464
w2:enter:1529569464
w2:end:1529569464
w2:enter:1529569466
w2:end:1529569466
w3:enter:1529569466
w3:end:1529569466

# 我們註釋w3程式碼 並開啟w2裡的sleep(3)執行結果
# 執行體時間 > 間隔時間
# 我們發現下一次執行時間是上一次執行完成時間
w2:enter:1529570041
w2:end:1529570046
w2:enter:1529570046
w2:end:1529570051
w2:enter:1529570051
w2:end:1529570056
w2:enter:1529570056
w2:end:1529570061
w2:enter:1529570061
w2:end:1529570066
w2:enter:1529570066

# 我們註釋w3程式碼 並開啟w2裡的sleep(1)執行結果
# 執行體時間<=間隔時間
# 我們發現下一次執行時間是正常間隔後執行時間
w2:enter:1529570098
w2:end:1529570099
w2:enter:1529570100
w2:end:1529570101
w2:enter:1529570102
w2:end:1529570103
w2:enter:1529570104

# 我們開啟w3裡的sleep,然後再執行結果
# 某個觀察者間隔時間受執行體影響,且多個觀察者會互相影響間隔時間
w2:enter:1529569484
w2:end:1529569484
w3:enter:1529569484
w3:end:1529569487
w3:enter:1529569487
w3:end:1529569490
w2:enter:1529569490
w2:end:1529569490
w2:enter:1529569490
w2:end:1529569490
w3:enter:1529569490
w3:end:1529569493
w3:enter:1529569493
w3:end:1529569496
w2:enter:1529569496
w2:end:1529569496
w2:enter:1529569496
w2:end:1529569496
w3:enter:1529569496

總結

如果單個watcher執行體時間 > 間隔時間,那麼下一次執行時間就是執行體完成時間
如果單個watcher執行體時間 <= 間隔時間,那麼下一次執行時間就是間隔後執行時間
如果多個watcher,各執行體的時間相互影響對方

EvPeriodic 將嘗試在這種模式下執行回撥,在當`time = offset ( mod interval )下一個可能的時間,不管任何時間跳躍。

reschedule_cb

手動重排程模式。在這種模式reschedule_cb是可呼叫。

間隔和偏移都被忽略了。相反,每次週期性觀察者被排程時,重新排程回撥(reschedule_cb)將首先以觀察者的方式呼叫,而當前時間作為第二個引數。

這個回撥永遠不能停止或破壞這個或任何其他週期性觀察者,並且不能呼叫任何事件迴圈函式或方法。停止它會先返回1000,再停止。一個EvPrepare觀察者可以用於此任務。

它必須根據傳遞的時間值(也就是說,大於或等於第二個引數的最低時間值。)返回下一次觸發。它通常會在呼叫回撥之前被呼叫,但也可能在其他時候被呼叫。

程式碼

<?php
function reschedule_cb_10dot5 ($watcher, $now) {
    return $now + (10.5 - fmod($now, 10.5));
}

function reschedule_cb_10s ($watcher, $now) {
    return $now + 10.;
}

//PHP7.0版本不支援ev1.0.4版本,目前發現bug無法正常根據reschedule_cb走,會意外的執行不可預測
//PHP5.6可正常,同樣下次執行收執行體裡的時間影響
$w5 = new EvPeriodic(0.0, 0.0, "reschedule_cb_10s", function ($w, $revents) {
    echo "w5:enter:", time(), PHP_EOL;
    sleep(15);
    echo "w5:end:", time(), PHP_EOL;
});

Ev::run();

執行結果

w5:enter:1529638365
w5:end:1529638380
w5:enter:1529638380
w5:end:1529638395
w5:enter:1529638395
w5:end:1529638410
w5:enter:1529638410
w5:end:1529638425
w5:enter:1529638425
w5:end:1529638440
w5:enter:1529638440
w5:end:1529638455
w5:enter:1529638455
w5:end:1529638470
w5:enter:1529638470
w5:end:1529638485
w5:enter:1529638485
w5:end:1529638500
w5:enter:1529638500
w5:end:1529638515
w5:enter:1529638515

# php 5.6
# php --ri ev
Ev擴充套件資訊
Ev support => enabled
Debug support => disabled
Version => 1.0.4
[root@localhost libev]# Version => 1.0.4

相關文章