0

0

纯PHP实现定时器任务(Timer)

php中文网

php中文网

发布时间:2016-06-21 08:46:29

|

1661人浏览过

|

来源于php中文网

原创

 定时器任务,在WEB应用比较常见,如何使用PHP实现定时器任务,大致有两种方案:1)使用Crontab命令,写一个shell脚本,在脚本中调用PHP文件,然后定期执行该脚本;2)配合使用ignore_user_abort()和set_time_limit(),使脚本脱离浏览器运行。前者是利用Linux的特性,和PHP本身没有多大关系,后者使用场景有限,且只能由一次HTTP请求触发该脚本,执行完后退出。那么我们如何使用纯PHP实现纯粹的定时器任务,且能适应认识任务业务需求?

 

立即学习PHP免费学习笔记(深入)”;

Huawei LiteOS物联网操作系统
Huawei LiteOS物联网操作系统

Huawei LiteOS是华为面向物联网领域开发的一个基于实时内核的轻量级操作系统。本项目属于华为物联网操作系统Huawei LiteOS源码,现有基础内核支持任务管理、内存管理、时间管理、通信机制、中断管理、队列管理、事件管理、定时器等操作系统基础组件,更好地支持低功耗场景,支持tickless机制,支持定时器对齐。 同时提供端云协同能力,集成了LwM2M、CoAP、mbedtls、LwIP全

下载

基础知识

 

立即学习PHP免费学习笔记(深入)”;

  此程序在Linux下开发,以cli模式运行,一下是基本知识的简要介绍。

 

立即学习PHP免费学习笔记(深入)”;

CLI:PHP的命令行模式,常见的WEB应用使用的是fpm;

进程:进程是程序运行的基本单元,进程之间是独立运行且互不干扰的,有独立的运行空间,每个进程都有一个进程控制块;

进程间通信:既然进程是独立运行,我们需要一种机制保证不同进程信息的交换,进程间通信主要包括:管道,IPC(共享内存,信号,消息队列),套接字;

PCNTL扩展:PHP的一个进程扩展,主要用到pcntl_alarm()函数,详细介绍请查阅官网.

实现原理    

 

立即学习PHP免费学习笔记(深入)”;

  用一个三维数组保存所有需要执行的任务,一级索引为时间戳,值为执行任务的方法、回调参数等,具体数组形式如下:

 

立即学习PHP免费学习笔记(深入)”;

 

立即学习PHP免费学习笔记(深入)”;

 

array(
        '1438156396' => array(
                array(1,array('Class','Func'), array(), true),  
        )
)
说明:
1438156396 时间戳
array(1,array('Class','Func'), array(), true) 
参数依次表示: 执行时间间隔,回调函数,传递给回调函数的参数,是否持久化(ture则一直保存在数据中,否则执行一次后删除)
 

 

立即学习PHP免费学习笔记(深入)”;

 

立即学习PHP免费学习笔记(深入)”;

  这些任务可以是任意类的方法。既然是定时任务,我们需要一个类似计时的东东,此方案采用信号量去做,每一秒向当前进程发送SIGALRM信号,并捕获该信号,触发信号处理函数,循环遍历数据,判断是否有当前时间需要执行的任务。如果有则采用回调方式触发,并把参数传递给该方法。

 

立即学习PHP免费学习笔记(深入)”;

 

  1 <?php
  2 /**
  3 *定时器
  4 */
  5 class Timer
  6 {
  7     //保存所有定时任务
  8     public static $task = array();
  9 
 10         //定时间隔
 11         public static $time = 1;
 12 
 13         /**
 14     *开启服务
 15         *@param $time int
 16        */
 17     public static function run($time = null)
 18         {
 19         if($time)
 20             {
 21                     self::$time = $time;
 22             }
 23             self::installHandler();
 24             pcntl_alarm(1);
 25          }
 26         /**
 27         *注册信号处理函数
 28         */
 29         public static function installHandler()
 30         {
 31             pcntl_signal(SIGALRM, array('Timer','signalHandler'));
 32         }
 33 
 34         /**
 35         *信号处理函数
 36         */
 37         public static function signalHandler()
 38         {
 39             self::task();
 40         //一次信号事件执行完成后,再触发下一次
 41         pcntl_alarm(self::$time);
 42         }
 43 
 44         /**
 45         *执行回调
 46         */
 47         public static function task()
 48         {
 49             if(empty(self::$task))
 50             {//没有任务,返回
 51                     return ;
 52             }
 53             foreach(self::$task as $time => $arr)
 54         {
 55                     $current = time();
 56         
 57                 foreach($arr as $k => $job)
 58             {//遍历每一个任务
 59                         $func = $job['func'];    /*回调函数*/
 60                         $argv = $job['argv'];    /*回调函数参数*/
 61                 $interval = $job['interval'];    /*时间间隔*/
 62                         $persist = $job['persist'];    /*持久化*/
 63 
 64                         if($current == $time)
 65                         {//当前时间有执行任务
 66 
 67                     //调用回调函数,并传递参数
 68                                call_user_func_array($func, $argv);
 69                     
 70                     //删除该任务
 71                             unset(self::$task[$time][$k]);
 72                         }
 73                         if($persist)
 74                         {//如果做持久化,则写入数组,等待下次唤醒
 75                                self::$task[$current+$interval][] = $job;
 76                         }
 77             }
 78             if(empty(self::$task[$time]))
 79             {
 80                 unset(self::$task[$time]);
 81             }
 82             }
 83         }
 84 
 85         /**
 86         *添加任务
 87         */
 88         public static function add($interval, $func, $argv = array(), $persist = false)
 89         {
 90             if(is_null($interval))
 91             {
 92                 return;
 93             }
 94             $time = time()+$interval;
 95         //写入定时任务
 96         self::$task[$time][] = array('func'=>$func, 'argv'=>$argv, 'interval'=>$interval, 'persist'=>$persist);
 97         }
 98 
 99         /**
100         *删除所有定时器任务
101         */
102         public function dellAll()
103         {
104             self::$task = array();
105         }
106 }

 

立即学习PHP免费学习笔记(深入)”;

 

立即学习PHP免费学习笔记(深入)”;

  这是定时器类核心部分,有一个静态变量保存有所有需要执行的任务,这里为什么是静态的呢?大家自行思考.当进程接受到 SIGALRM 信号后,触发 signalHandler 函数,随后循序遍历数组查看是否有当前时间需要执行的任务,有则回调,并传递参数,删除当前job,随后检查是否要做持久化任务,是则继续将当前job写入事件数组等待下次触发,最后再为当前进程设置一个闹钟信号.可以看出这个定时器,只要触发一次就会从内部再次触发,得到自循环目的.

 

立即学习PHP免费学习笔记(深入)”;

 

 1 <?php
 2 
 3 class DoJob
 4 {
 5     public function job( $param = array() )
 6     {
 7         $time = time();
 8         echo "Time: {$time}, Func: ".get_class()."::".__FUNCTION__."(".json_encode($param).")\n";
 9     }
10 }

 

立即学习PHP免费学习笔记(深入)”;

 

立即学习PHP免费学习笔记(深入)”;

  这是回调类及函数,为方便说明,加入不少调试信息.Timer类及回调都有了,我们看看使用场景是怎么样的.

 

立即学习PHP免费学习笔记(深入)”;

 

 1 <?php
 2 
 3 require_once(__DIR__."/Timer.php");
 4 require_once(__DIR__."/DoJob.php");
 5 
 6 
 7 Timer::dellAll();
 8 
 9 Timer::add( 1, array('DoJob','job'), array(),true);
10 
11 Timer::add( 3, array('DoJob','job'),array('a'=>1), false);
12 
13 echo "Time start: ".time()."\n";
14 Timer::run();
15 
16 while(1)
17 {
18     sleep(1);
19     pcntl_signal_dispatch();
20 }

 

立即学习PHP免费学习笔记(深入)”;

 

立即学习PHP免费学习笔记(深入)”;

  代码非常短,这里注册了两个job,随后运行定时器,在一个无限循环里捕捉信号触发动作,如果不捕获将无法触发事先注册的处理函数.这样一个自循环的定时器开发完成.运行结果如下:

 

立即学习PHP免费学习笔记(深入)”;

  

 

立即学习PHP免费学习笔记(深入)”;

  如我们场景类添加的任务一样,在90的时候执行了两个任务,一个为持久化的不带参数的job,一个为非持久化带参数的job,随后非持久化job不再执行.

 

立即学习PHP免费学习笔记(深入)”;

总结

 

立即学习PHP免费学习笔记(深入)”;

在收到信号前,当前进程不能退出.这里我使用了条件永远为真的循环.在我们实际生产环境中,需要创造这么一个先决条件,比如说,我们有一组服务,这些服务都是一直运行的,不管是IO访问,等待socket链接等等,当前服务都不会终止,即使进程阻塞也不会有问题,这种场景,也就是有一个一直运行的服务中使用.

目前PHP只支持以秒为单位的触发,不支持更小时间单位,对位定时任务而言基本足够



PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

1142

2026.02.13

微博网页版主页入口与登录指南_官方网页端快速访问方法
微博网页版主页入口与登录指南_官方网页端快速访问方法

本专题系统整理微博网页版官方入口及网页端登录方式,涵盖首页直达地址、账号登录流程与常见访问问题说明,帮助用户快速找到微博官网主页,实现便捷、安全的网页端登录与内容浏览体验。

371

2026.02.13

Flutter跨平台开发与状态管理实战
Flutter跨平台开发与状态管理实战

本专题围绕Flutter框架展开,系统讲解跨平台UI构建原理与状态管理方案。内容涵盖Widget生命周期、路由管理、Provider与Bloc状态管理模式、网络请求封装及性能优化技巧。通过实战项目演示,帮助开发者构建流畅、可维护的跨平台移动应用。

245

2026.02.13

TypeScript工程化开发与Vite构建优化实践
TypeScript工程化开发与Vite构建优化实践

本专题面向前端开发者,深入讲解 TypeScript 类型系统与大型项目结构设计方法,并结合 Vite 构建工具优化前端工程化流程。内容包括模块化设计、类型声明管理、代码分割、热更新原理以及构建性能调优。通过完整项目示例,帮助开发者提升代码可维护性与开发效率。

37

2026.02.13

Redis高可用架构与分布式缓存实战
Redis高可用架构与分布式缓存实战

本专题围绕 Redis 在高并发系统中的应用展开,系统讲解主从复制、哨兵机制、Cluster 集群模式及数据分片原理。内容涵盖缓存穿透与雪崩解决方案、分布式锁实现、热点数据优化及持久化策略。通过真实业务场景演示,帮助开发者构建高可用、可扩展的分布式缓存系统。

114

2026.02.13

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

77

2026.02.12

雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法
雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法

本专题系统整理雨课堂网页版官方入口及在线登录方式,涵盖账号登录流程、官方直连入口及平台访问方法说明,帮助师生用户快速进入雨课堂在线教学平台,实现便捷、高效的课程学习与教学管理体验。

17

2026.02.12

豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法
豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法

本专题汇总豆包AI官方网页版入口及在线使用方式,涵盖智能写作工具、图片生成体验入口和官网登录方法,帮助用户快速直达豆包AI平台,高效完成文本创作与AI生图任务,实现便捷智能创作体验。

863

2026.02.12

PostgreSQL性能优化与索引调优实战
PostgreSQL性能优化与索引调优实战

本专题面向后端开发与数据库工程师,深入讲解 PostgreSQL 查询优化原理与索引机制。内容包括执行计划分析、常见索引类型对比、慢查询优化策略、事务隔离级别以及高并发场景下的性能调优技巧。通过实战案例解析,帮助开发者提升数据库响应速度与系统稳定性。

123

2026.02.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP函数之array数组函数视频讲解
PHP函数之array数组函数视频讲解

共76课时 | 26.2万人学习

Excel 教程
Excel 教程

共162课时 | 18.7万人学习

Pandas 教程
Pandas 教程

共15课时 | 1.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号