搜索
查看: 4917|回复: 0

PHP 实现定时器任务(Timer)

[复制链接]

330

主题

177

回帖

1071

积分

vip用户

积分
1071

注册会员活跃会员热心会员

QQ
发表于 2018-5-17 09:26:08 来自手机 | 显示全部楼层 |阅读模式
定时器,在 WEB 应用中比较常见,比如:每天凌晨2点自动备份数据库,这个功能就要使用定时器。现在使用的定时器方案大多数都是 Linux 的 Crontab 命令(或者是 Window 中的任务计划),写一个 shell 脚本,在脚本中执行操作。其实 PHP 也是完全可以实现定时器功能的,这里需要使用 PCNTL 模块,此模块默认是没有安装的,如果没有安装只需要在编译 PHP 的时候,添加 --enable-pcntl 配置选项重新编译 PHP 即可。



直接上代码,代码都是说明注释。如果不能,请留言:
[pre]
<?php
class Timer
{
    private $seconds = 1; // 秒数,每隔多少秒会执行一次
    private $callback = ""; // 功能函数,即您要实现的功能
    private $isdaemon = false; // 是否开启守护进程

    // 构造函数,
    // 第一个是 秒数(正整数)
    // 第二个参数是一个 bool,是否开启守护进程
    // 第三个参数为要实现的功能
    public function __construct(int $seconds, $isdaemon = false, $callback = "")
    {
        if($seconds >= 0) $this->seconds = $seconds;
        $this->isdaemon = (bool)$isdaemon;

        // 保存第三个参数是一个匿名函数
        if($callback instanceof Closure)
        {
            $this->callback = $callback;
        } else {
            $this->callback = function() {};
        }
    }

    // 程序运行
    public function start()
    {
        if($this->isdaemon)
            $this->start_daemon();
        
        // 安装一个信号处理器
        pcntl_signal(SIGALRM, array($this, 'installHandler'));

        // 启用异步信号处理
        pcntl_async_signals(true);

        // 设置闹钟信号
        pcntl_alarm($this->seconds);

        // 进入死循环,防止程序终止
        while(true);
    }

    // 信号处理函数
    public function installHandler()
    {
        // 调用客户需要操作的函数
        call_user_func($this->callback);

        // 重新设置闹钟
        pcntl_alarm($this->seconds);
    }

    // 开启守护进程
    public function start_daemon()
    {
        if(($pid = pcntl_fork()) < 0) {
            exit("start daemon error()");
        } else if($pid) { // 如果是父进程,则终止程序
            exit();
        } else {

        }
    }
}


// 客户端调用,每隔 1 秒打印一下当前的时间

// 第 1 个参数,表示每隔 1 秒执行一次
// 第 2 个参数,表示 不开启 守护进程
// 第 3 个参数,表示要做的功能
$timer = new Timer(1, false, function()
{
    echo date("Y-m-d H:i:s\n");
});
$timer->start();
?>
[/pre]
当然,我们也可以采用 swoole 这种扩展,如果用 swoole 的话,那是很简单的,一句话,就可以搞定。如:
[pre]
swoole_timer_tick(1000, function()
{
    echo date("Y-m-d H:i:s\n");
});
[/pre]
不管是直接用 PHP 来写,还是 swoole 来写,最都可以实现我们想要的功能。但是,在实际项目中,最好不要用 PHP 来实现定时器,还是利用  Linux 的 Crontab 效率更高些,也更方便些。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表