× 警告!旧版文档已经暂停维护,请查看新版文档。点击前往新版文档

Timer::tick

设置一个间隔时钟定时器,与after定时器不同的是tick定时器会持续触发,直到调用Timer::clear清除。

int Swoole\Timer::tick(int $msec, callable $callback, ...$params);

函数风格别名是swoole_timer_tick

  • $msec 指定时间,单位为毫秒。如1000表示1秒4.2.10以下版本最大不得超过 86400000
  • $callback_function 时间到期后所执行的函数,必须是可以调用的
  • 可以使用匿名函数的use语法传递参数到回调函数中
  • 定时器仅在当前进程空间内有效
  • 定时器是纯异步实现的,不能与阻塞IO的函数一起使用,否则定时器的执行时间会发生错乱

定时器在执行的过程中可能存在一定误差

回调函数

定时器触发的回调函数接受1+若干个参数。

function callbackFunction(int $timer_id, ...$params);
  • $timer_id 定时器的ID,可用于Timer::clear清除此定时器
  • $paramsTimer::tick传入的第三个参数$param,此参数也为可选参数

定时器校正

定时器回调函数的执行时间不影响下一次定时器执行的时间。实例:在0.002s设置了10mstick定时器,第一次会在0.012s执行回调函数,如果回调函数执行了5ms,下一次定时器仍然会在0.022s时触发,而不是0.027s

但如果定时器回调函数的执行时间过长,甚至覆盖了下一次定时器执行的时间。底层会进行时间校正,丢弃已过期的行为,在下一时间回调。如上面例子中0.012s时的回调函数执行了15ms,本该在0.022s产生一次定时回调。实际上本次定时器在0.027s才返回,这时定时早已过期。底层会在0.032s时再次触发定时器回调。

协程模式

在协程环境下Timer::tick回调中会自动创建一个协程,可以直接使用协程相关API,无需调用go创建协程。

可设置enable_coroutine关闭自动创建协程

使用示例

Swoole\Timer::tick(1000, function(){
    echo "timeout\n";
});

正确示例

Swoole\Timer::tick(3000, function (int $timer_id, $paramA, $paramB) {
    echo "after 3000ms.\n";
    Swoole\Timer::tick(14000, function () {
        echo "after 14000ms.\n";
    });
}, $paramA, $paramB);

错误示例

Swoole\Timer::tick(3000, function () {
   echo "after 3000ms.\n";
   sleep(14);
   echo "after 14000ms.\n";
});

  • 小草的影子

    在request回调函数中使用swoole_timer_tick 设置1000时会通知三次 设置2,3秒就是正常的

  • single

    swoole_timer_tick 这里的第三个参数$param 是什么意思? 是callback函数的参数还是什么?

  • A_钟某某

        swoole_timer_tick(6000, function () {
            echo 'callback_function1   '.time()."\n";
                        sleep(3);
         });  这里执行间隔为什么会是12秒?
    

  • 哈哈哈

    不是不让用sleep么?感觉你这么写,就变成3+6+3,在底12秒多的时候才被执行。

  • 哈哈哈

    哦,不对,是3+3+3+3,先sleep3,然后timer执行3秒,再sleep3秒,timer再执行3秒,这样就到第12秒才开始执行echo

  • 哈哈哈

    哦,不对,是3+3+3+3,先sleep3,然后timer执行3秒,再sleep3秒,timer再执行3秒,这样就到第12秒才开始执行echo

  • A_钟某某

    swoole_timer_tick(6000, function () { echo 'callback_function1 '.time()."\n"; sleep(2); }); 那请问这段代码为啥又正常执行

  • www

    同时放两个 时间不同的 swoole_timer_tick 会出问题

  • 苏东坡

    两个client时,定时器的的间隔会减半

  • lovyhui

    我测试发现swoole_timer_tick不会触发onTimer回调. 这里的函数onTimer是swoole_timer_add函数添加的定时器触发的吧回调吧, 不是swoole_timer_tick. 而且上面参数说明里说"$callback_function 时间到期后所执行的函数,必须是可以调用的。callback函数不接受任何参数"

  • Hi

    这个定时器对主线程有没有影响

  • 一场白雪

    能用 协成吗 在定时器里面

  • `ヽ viva

    @韩天峰 task进程池里面用Tick定时器每两秒查询数据,然后循环数据里面用swoole_timer_after 延时5秒丢给finish 在服务端打印的结果是一瞬间就全部把结果输出了,帮忙指点一下,我该怎么弄?

  • `ヽ viva

    为什么没有达到我的需求,每隔几秒输出结果给finish,而是一瞬间全部抛给了finish ,我开了一个wokerj进程和一个task进程

  • `ヽ viva

    看到文档里面写了swoole_timer_after 相当于setTimeout,只能触发一次,如果业务逻辑需要用到sleep几秒执行,连续这样的操作,该怎么样做?

  • Sin

    为什么在Task里面是有swoole_timer_tick?直接在onwokerstart进程选择一个进行设置定时器进行处理,task进程里面加一个swoole_timer_tick每次的投递任务你又生成了一个进程?@

  • Sin

    一般来说是有swoole_timer_tick处理一些和前端或者使用scoket机制进行实时的通信你可以把需要的投递的数据放到队列中,然后后台进行启动一个进程进行处理即可调用 RedisServer异步投递数据交互前端即可

  • 18638226306

    可以在 onrequest 回调里面添加 定时任务吗