PHP定時執行任務實現方法詳解(Timer)

2022-10-06 10:09:12 字數 3033 閱讀 5094

下面通過理論講解,例項分析,效果展示的方式給大家分享下php定時執行任務實現方法。

定時器任務,在web應用比較常見,如何使用php實現定時器任務,大致有兩種方案:

1)使用crontab命令,寫乙個shell指令碼,在指令碼中呼叫php檔案,然後定期執行該指令碼;

2)配合使用ignore_user_abort()和set_time_limit(),使指令碼脫離瀏覽器執行。

前者是利用linux的特性,和php本身沒有多大關係,後者使用場景有限,且只能由一次http請求觸發該指令碼,執行完後退出。那麼我們如何使用純php實現純粹的定時器任務,且能適應認識任務業務需求?

基礎知識

此程式在linux下開發,以cli模式執行,一下是基本知識的簡要介紹。

cli:php的命令列模式,常見的web應用使用的是fpm;

程序:程序是程式執行的基本單元,程序之間是獨立執行且互不干擾的,有獨立的執行空間,每個程序都有乙個程序控制塊;

程序間通訊:既然程序是獨立執行,我們需要一種機制保證不同程序資訊的交換,程序間通訊主要包括:管道,ipc(共享記憶體,訊號,訊息佇列),套接字;

pcntl擴充套件:php的乙個程序擴充套件,主要用到pcntl_alarm()函式,詳細介紹請查閱官網.

實現原理    

用乙個三維陣列儲存所有需要執行的任務,一級索引為時間戳,值為執行任務的方法、**引數等,具體陣列形式如下:

複製** **如下:

array(

'1438156396' = array(

array(1,array('class','func'), array(), true), 

&nbswww.cppcns.comp;       )

)說明:

1438156396 時間戳

複製** **如下:

array(1,array('class','func'), array(), true)

引數依次表示: 執行時間間隔,**函式,傳遞給**函式的引數,是否持久化(ture則一直儲存在資料中,否則執行一次後刪除)

這些任務可以是任意類的方法。既然是定時任務,我們需要乙個類似計時的東東,此方案採用訊號量去做,每一秒向當前程序傳送sigalrm訊號,並捕獲該訊號,觸發訊號處理函式,迴圈遍歷資料,判斷是否有當前時間需要執行的任務。如果有則採用**方式觸發,並把引數傳遞給該方法。

<?php /**

*定時器

*/ class timer

self::installhandler();

pcntl_alarm(1);

}/**

*註冊訊號處理函式

*/public static function installhandler()

/***訊號處理函式

*/public static function signalhandler()

/***執行**

*/public static function task()

foreach(self::$task as $time => $arr)

if($persist)

}if(empty(self::$task[$time]))}}

/***新增任務

*/public static function add($interval, $func, $ar** = array(), $persist = false)

$time = time()+$interval;

//寫入定時任務

self::$task[$time] = array('func'=>$func, 'ar**'=>$ar**, 'interval'=>$interval, 'persist'=>$persist);

}/**

*刪除所有定時器任務

*/public function dellall()

}這是定時器類核心部分,有乙個靜態變數儲存有所有需要執行的任務,這裡為什麼是靜態的呢?大家自行思考.當程序接受到 sigalrm 訊號後,觸發 signalhandler 函式,隨後循序遍歷陣列檢視是否有當前時間需要執行的任務,有則**,並傳遞引數,刪除當前job,隨後檢查是否要做持久化任務,是則繼續將當前job寫入事件陣列等待下次觸發,最後再為當前程序設定乙個鬧鐘訊號.可以看出這個定時器,只要觸發一次就會從內部再次觸發,得到自迴圈目的.

<?php class dojob

, func: ".get_class()."::".__function__."(".json_encode($param).")\n";

} }這是**類及函式,為方便說明,加入不少除錯資訊.timer類及**都有了,我們看看使用場景是怎麼樣的.

<?php require_once(__dir__."/timer.php");

require_once(__dir__."/dojob.php");

timer::dellall();

timer::add( 1, array('dojob','job'), array(),true);

timer::add( 3, array('dojob','job'),array('a'=>1), false);

echo "time start: ".time()."\n";

timer::run();

while(1)

**非常短,這裡註冊了兩個job,隨後執行定時器,在乙個無限迴圈裡捕捉訊號觸發動作,如果不捕獲將無法觸發事先註冊的處理函式.這樣乙個自迴圈的定時器開發完成.執行結果如下:

如我們場景類新增的任務一樣,在90的時候執行了兩個任務,乙個為持久化的不帶引數的job,乙個為非持久化帶引數的job,隨後非持久化job不再執行.

總結在收到訊號前,當前程序不能退出.這裡我使用了條件永遠為真的迴圈.在我們實際生產環境中,需要創造這麼乙個先決條件,比如說,我們有一組服務,這些服務都是一直執行的,不管是io訪問,等待socket鏈結等等,當前服務都不會終止,即使程序阻塞也不會有問題,這種場景,也就是有乙個一直執行的服務中使用.

目前php只支援以秒為單位的觸發,不支援更小時間單位,對位定時任務而言基本足夠

本文標題: php定時執行任務實現方法詳解(timer)

本文位址:

php定時執行任務實現方法詳解

每個php指令碼都限制了執行時間,所以我們需要通過 set time limit 來設定乙個指令碼的執行時間為無限長 然後使用 flush 和 ob flush 來清除伺服器緩衝區,隨時輸出指令碼的返回值。當我們執行後,每隔5秒鐘,我們會得到一行 hello world header content...

PHP實現定時執行任務的方法

這篇文章主要介紹了php實現定時執行任務的方法,涉及到ignore user abort函式忽略指令碼終止的使用及sleep函式延緩執行等的應用,需要的朋友可以參考下 ignore user abort true 客戶端斷開時忽略指令碼中止 允許指令碼一直執行 set time limit 0 設定...

php定時執行任務設定詳解

url 複製 url 如下 d cd php php.exe d wwwroot dingshi.php 定時執行的指令碼檔案的路徑我們可以測試一下dingshi.php url 複製 url 如下 file put contents a.php test 我們雙擊一下test.bat,然後看下a....