[PHP]详谈可控制的定时器(附源码)

qsuron 发布于 2015-04-16 PHP 288 次阅读 6 条评论 1212 字 预计阅读时间: 6 分钟


一、引言

恰逢公司的项目需要用到定时器,在网上搜了许多的资料,虽说PHP本身是无状态的语言,用来做定时器非常的麻烦和耗资源,但是实际应用上还是少不了的。方法有几个:

1,利用计算机系统本身的计划任务

2,利用js前台刷新页面定时访问PHP文件

3,利用PHP死循环长连接

由于1,2两种办法都没办法很好地对定时器进行很好的控制,而本篇主要讲的是可控制的定时器,因此我们来详看第三种方法。

二、思路

思路其实不复杂,利用 while(true)死循环让PHP脚本一直处于执行的状态。但是!要注意的是,PHP本身是有一个机制会中断无响应的脚本的,因此,我们要加上。

ignore_user_abort(false);//当用户关闭页面时服务停止
set_time_limit(0);  //设置执行时间,单位是秒。0表示不限制。

先给出一个基本的范式,其中有个人的测试程序:

<?php
ignore_user_abort(); // run script. in background
set_time_limit(0); // run script. forever
interval=30; // do every 15 minutes...
do{fp = fopen('text3.txt','a');
fwrite(fp,'test');
fclose(fp);
sleep($interval); // wait 15 minutes
}while(true);
?>

 

首先运行该程序,然后关闭该页面,程序仍然运行中,test会每隔30秒的填补到text3.txt文件。

至此一个简单的定时器算是OK了,但是它是不可控制的,因为程序处于死循环中,是无法接受外界的数据的。

那么我们要实现可控制,怎么办呢?解决办法是有的,这里很多种办法,比如读数据库,读文件,我带来的方法也简单,就是用PHP本身的INCLUDE,这样效率也不会太低,消耗的资源也不会太过于大!

即:在死循环中,加一个  if();,判断的条件,就是  $flag = include '路径/配置文件.php';

而这个   [配置文件.php] 的内容很简单,就一句:<?php return true; ?>

当你需要这个定时器停下来的时候,用文件函数fopen打开这个配置文件,然后替换true为false就可以了,这就是基本的思路!

三、源码例子

 

<?php

ignore_user_abort (); // 即使Client断开(如关掉浏览器),PHP脚本也可以继续执行.
set_time_limit ( 0 ); // 执行时间为无限制,php默认的执行时间是30秒,通过set_time_limit(0)可以让程序无限制的执行下去


class money extends admin {

	public timer_switch;			//定时器-开关-文件
	publictimer_h;				//定时器-时-文件
	public timer_m;				//定时器-分-文件
	publictimer_delay;			//定时器-间隔时间(秒)-文件
	public timer_value;			//利息利率

	public function __construct(){
		parent::__construct();this->db = System::load_sys_class("model");
		this->timer_switch = dirname(__FILE__)."\\timer_switch.php";this->timer_h = dirname(__FILE__)."\\timer_h.php";
		this->timer_m = dirname(__FILE__)."\\timer_m.php";this->timer_delay = dirname(__FILE__)."\\timer_delay.php";
		this->timer_value = dirname(__FILE__)."\\timer_value.php";
	}

	public function index(){
		if(isset(_POST['submit'])){
			this->h(_POST['h']);
			this->m(_POST['m']);
			this->delay(_POST['delay']);
			this->value(_POST['value']);
			msg = '【保存成功】';
		}switch = include this->timer_switch;h = include this->timer_h;m = include this->timer_m;delay = include this->timer_delay;value = include this->timer_value;
		includethis->tpl(ROUTE_M,'money_index');
	}

	public function h(s){string = '<?php return "'.s.'";?>';
		write_inc(this->timer_h,string,true);
	}

	public function m(s){
		string = '<?php return "'.s.'";?>';
		write_inc(this->timer_m,string,true);
	}

	public function delay(s){string = '<?php return "'.s.'";?>';
		write_inc(this->timer_delay,string,true);
	}

	public function value(s){
		string = '<?php return "'.s.'";?>';
		write_inc(this->timer_value,string,true);
	}

	public function stop(){
		string = '<?php return "stop";?>';
		write_inc(this->timer_switch,string,true);this->index();
	}

	public function start(){
		//必须为暂停状态才可以开始
		timer_switch = includethis->timer_switch;
		if(timer_switch!='stop'){fp = fopen('c:/func.txt','a');
			fwrite(fp,date("Y-m-d TH:i:s Z").".结束定时器.\r\n");
			fclose(fp);
			die();
		}else{
			fp = fopen('c:/func.txt','a');
			fwrite(fp,date("Y-m-d TH:i:s Z").".启动定时器.\r\n");
			fclose(fp);string = '<?php return "start";?>';
			write_inc(this->timer_switch,string,true);
		}
		//进入定时器
		do{
			timer_switch = includethis->timer_switch;
			timer_h = includethis->timer_h;
			timer_m = includethis->timer_m;
			timer_delay = includethis->timer_delay;
			h = intval(date("H"));m = intval(date("i"));
			//判断时间
			if (h ==timer_h && m ==timer_m) {
				fp = fopen('c:/func.txt','a');
				fwrite(fp,date("Y-m-d TH:i:s Z").".执行任务了.\r\n");
				fclose(fp);this->calc();
			} else {
				fp = fopen('c:/func.txt','a');
				fwrite(fp,date("Y-m-d TH:i:s Z").".距离执行时间还有".(((timer_h-h)%24)*60+(timer_m-m)%60)."分钟.\r\n");
				fclose(fp);
			}
			//延迟
			sleep(timer_delay);
			//判断是否关闭
			if(timer_switch=="stop"){fp = fopen('c:/func.txt','a');
				fwrite(fp,date("Y-m-d TH:i:s Z").".终止.\r\n");
				fclose(fp);
				this->ing_off();
				die();
			}
		}while(true);

	}


	public function calc(){


	}



}


	function write_inc(path,strings,type=false){
		if (type==false)
			file_put_contents(path,strings,FILE_APPEND);
		else
			file_put_contents(path,$strings);
	}



?>

 

 

代码敲的累了,换个中文悠闲悠闲。
最后更新于 2015-04-16