WorkerMan::Timer解析

    /**
     * Init.
     *
     * @param \Workerman\Events\EventInterface $event
     * @return void
     */
    public static function init($event = null)
    {
        if ($event) {
            self::$_event = $event;
        } else {
            // 初始化,定义一个SIGALRM信号处理器.
            pcntl_signal(SIGALRM, array('\Workerman\Lib\Timer', 'signalHandle'), false);
        }
    }

    /**
     * ALARM signal handler.
     *
     * @return void
     */
    public static function signalHandle()
    {
        if (!self::$_event) {
            // 当触发第一次SIGALRM信号后,每次调用都进行一次触发,保证定时任务持续运行.
            pcntl_alarm(1);
            self::tick();
        }
    }

    /**
     * Add a timer.
     *
     * @param int      $time_interval
     * @param callback $func
     * @param mixed    $args
     * @param bool     $persistent
     * @return int/false
     */
    public static function add($time_interval, $func, $args = array(), $persistent = true)
    {
        if ($time_interval <= 0) {
            echo new Exception("bad time_interval");
            return false;
        }

        // 使用的是事件回调定时任务.
        if (self::$_event) {
            return self::$_event->add($time_interval,
                $persistent ? EventInterface::EV_TIMER : EventInterface::EV_TIMER_ONCE, $func, $args);
        }

        if (!is_callable($func)) {
            echo new Exception("not callable");
            return false;
        }

        // 第一次添加定时任务时,需要触发一下SIGALRM.
        if (empty(self::$_tasks)) {
            pcntl_alarm(1); // 1s后触发SIGALRM信号.
        }

        // 根据运行时间将定时任务放入任务队列.
        $time_now = time();
        $run_time = $time_now + $time_interval;
        if (!isset(self::$_tasks[$run_time])) {
            self::$_tasks[$run_time] = array();
        }
        self::$_tasks[$run_time][] = array($func, (array)$args, $persistent, $time_interval);
        return 1;
    }


    /**
     * Tick.
     *
     * @return void
     */
    public static function tick()
    {
        // 如果没有定时任务,取消信号闹钟.
        if (empty(self::$_tasks)) {
            pcntl_alarm(0);
            return;
        }

        $time_now = time();
        // 遍历任务队列.
        // 任务格式:
        /**
         * array(
         *  $run_time => array(
         *      array(
         *          $func, $args, $persistent, $time_interval,
         *      ),
         *      array(
         *          $func, $args, $persistent, $time_interval,
         *      ),
         *      .....
         *  ),
         * )
         */
        foreach (self::$_tasks as $run_time => $task_data) {
            // 判断当前时间是否超过运行时间,如果超过则执行任务.
            if ($time_now >= $run_time) {
                foreach ($task_data as $index => $one_task) {
                    $task_func     = $one_task[0];
                    $task_args     = $one_task[1];
                    $persistent    = $one_task[2];
                    $time_interval = $one_task[3];
                    try {
                        // 执行函数回调.
                        call_user_func_array($task_func, $task_args);
                    } catch (\Exception $e) {
                        echo $e;
                    }
                    // 如果任务是持久化,需要将次任务重新放入任务队列.
                    if ($persistent) {
                        self::add($time_interval, $task_func, $task_args);
                    }
                }
                // 删除已经执行过的任务.
                unset(self::$_tasks[$run_time]);
            }
        }
    }

    /**
     * Remove a timer.
     *
     * @param mixed $timer_id
     * @return bool
     */
    public static function del($timer_id)
    {
        // 删除指定事件的定时任务.
        if (self::$_event) {
            return self::$_event->del($timer_id, EventInterface::EV_TIMER);
        }

        return false;
    }

    /**
     * Remove all timers.
     *
     * @return void
     */
    public static function delAll()
    {
        // 清空所有定时任务.
        self::$_tasks = array();
        pcntl_alarm(0);
        if (self::$_event) {
            self::$_event->clearAllTimer();
        }
    }


一个持久化定时任务的示例:


require_once __DIR__ . '/Autoloader.php';

function testTime()
{
    echo "the time : " . date('Y-m-d H:i:s') . "\n";
}

\Workerman\Lib\Timer::init();

\Workerman\Lib\Timer::add(1, 'testTime');

while (1) {
    pcntl_signal_dispatch();
}

WorkerMan::Timer解析_第1张图片

你可能感兴趣的:(workerman)