php基于協(xié)程實(shí)現(xiàn)異步的方法分析
本文實(shí)例講述了php基于協(xié)程實(shí)現(xiàn)異步的方法。分享給大家供大家參考,具體如下:
github上php的協(xié)程大部分是根據(jù)這篇文章實(shí)現(xiàn)的:http://nikic.github.io/2012/12/22/Cooperative-multitasking-using-coroutines-in-PHP.html。
它們最終的結(jié)果都是把回調(diào)變成了優(yōu)雅的順序執(zhí)行的代碼,但還是阻塞的,不是真正的異步。
比如最熱門的:https://github.com/recoilphp/recoil
先安裝:
composer require recoil/recoil
執(zhí)行:
<?php //recoil.php include __DIR__ . '/vendor/autoload.php'; use Recoil\React\ReactKernel; $i = 100000; ReactKernel::start(task1()); ReactKernel::start(task2()); function task1(){ global $i; echo "wait start" . PHP_EOL; while ($i-- > 0) { yield; } echo "wait end" . PHP_EOL; }; function task2(){ echo "Hello " . PHP_EOL; yield; echo "world!" . PHP_EOL; }
結(jié)果:
wait start
//等待若干秒
wait end
Hello
world!
我本來是想讓兩個(gè)任務(wù)并行,結(jié)果兩個(gè)任務(wù)變成了串行,中間等待的時(shí)間什么事情都干不了。React響應(yīng)式的編程是嚴(yán)格禁止這種等待的,所以我就參照unity3d的協(xié)程自己寫了個(gè)php版本的。上代碼:
<?php //Coroutine.php //依賴swoole實(shí)現(xiàn)的定時(shí)器,也可以用其它方法實(shí)現(xiàn)定時(shí)器 class Coroutine { //可以根據(jù)需要更改定時(shí)器間隔,單位ms const TICK_INTERVAL = 1; private $routineList; private $tickId = -1; public function __construct() { $this->routineList = []; } public function start(Generator $routine) { $task = new Task($routine); $this->routineList[] = $task; $this->startTick(); } public function stop(Generator $routine) { foreach ($this->routineList as $k => $task) { if($task->getRoutine() == $routine){ unset($this->routineList[$k]); } } } private function startTick() { swoole_timer_tick(self::TICK_INTERVAL, function($timerId){ $this->tickId = $timerId; $this->run(); }); } private function stopTick() { if($this->tickId >= 0) { swoole_timer_clear($this->tickId); } } private function run() { if(empty($this->routineList)){ $this->stopTick(); return; } foreach ($this->routineList as $k => $task) { $task->run(); if($task->isFinished()){ unset($this->routineList[$k]); } } } } class Task { protected $stack; protected $routine; public function __construct(Generator $routine) { $this->routine = $routine; $this->stack = new SplStack(); } /** * [run 協(xié)程調(diào)度] * @return [type] [description] */ public function run() { $routine = &$this->routine; try { if(!$routine){ return; } $value = $routine->current(); //嵌套的協(xié)程 if ($value instanceof Generator) { $this->stack->push($routine); $routine = $value; return; } //嵌套的協(xié)程返回 if(!$routine->valid() && !$this->stack->isEmpty()) { $routine = $this->stack->pop(); } $routine->next(); } catch (Exception $e) { if ($this->stack->isEmpty()) { /* throw the exception */ return; } } } /** * [isFinished 判斷該task是否完成] * @return boolean [description] */ public function isFinished() { return $this->stack->isEmpty() && !$this->routine->valid(); } public function getRoutine() { return $this->routine; } }
測試代碼:
<?php //test.php require 'Coroutine.php'; $i = 10000; $c = new Coroutine(); $c->start(task1()); $c->start(task2()); function task1(){ global $i; echo "wait start" . PHP_EOL; while ($i-- > 0) { yield; } echo "wait end" . PHP_EOL; }; function task2(){ echo "Hello " . PHP_EOL; yield; echo "world!" . PHP_EOL; }
結(jié)果:
wait start
Hello
world!
//等待幾秒,但不阻塞
wait end
更多關(guān)于PHP相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《PHP擴(kuò)展開發(fā)教程》、《PHP網(wǎng)絡(luò)編程技巧總結(jié)》、《php curl用法總結(jié)》、《PHP數(shù)組(Array)操作技巧大全》、《PHP數(shù)據(jù)結(jié)構(gòu)與算法教程》、《php程序設(shè)計(jì)算法總結(jié)》及《php字符串(string)用法總結(jié)》
希望本文所述對(duì)大家PHP程序設(shè)計(jì)有所幫助。
- 詳解php協(xié)程知識(shí)點(diǎn)
- PHP生成器(generator)和協(xié)程的實(shí)現(xiàn)方法詳解
- PHP7下協(xié)程的實(shí)現(xiàn)方法詳解
- 關(guān)于PHP中協(xié)程和阻塞的一些理解與思考
- PHP 進(jìn)程池與輪詢調(diào)度算法實(shí)現(xiàn)多任務(wù)的示例代碼
- PHP定時(shí)執(zhí)行計(jì)劃任務(wù)的多種方法小結(jié)
- php定時(shí)計(jì)劃任務(wù)的實(shí)現(xiàn)方法詳解
- php守護(hù)進(jìn)程 加linux命令nohup實(shí)現(xiàn)任務(wù)每秒執(zhí)行一次
- PHP中使用sleep函數(shù)實(shí)現(xiàn)定時(shí)任務(wù)實(shí)例分享
- PHP實(shí)現(xiàn)簡單的協(xié)程任務(wù)調(diào)度demo示例
相關(guān)文章
PHP學(xué)習(xí)散記_編碼(json_encode 中文不顯示)
今天使用json_encode轉(zhuǎn)換數(shù)組的時(shí)候,出現(xiàn)了中文不顯示的情況。2011-11-11php中strstr、strrchr、substr、stristr四個(gè)函數(shù)的區(qū)別總結(jié)
這篇文章主要介紹了php中strstr、strrchr、substr、stristr四個(gè)函數(shù)的區(qū)別總結(jié),這4個(gè)函數(shù)是PHP中常用的字符串相關(guān)函數(shù),需要的朋友可以參考下2014-09-09關(guān)于php操作mysql執(zhí)行數(shù)據(jù)庫查詢的一些常用操作匯總
本篇文章是對(duì)關(guān)于php操作mysql執(zhí)行數(shù)據(jù)庫查詢的一些常用操作進(jìn)行了詳細(xì)的匯總介紹,需要的朋友參考下2013-06-06PHP設(shè)計(jì)模式之結(jié)構(gòu)模式的深入解析
本篇文章是對(duì)PHP設(shè)計(jì)模式中的結(jié)構(gòu)模式進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06PHP實(shí)現(xiàn)的sqlite數(shù)據(jù)庫連接類
這篇文章主要介紹了PHP實(shí)現(xiàn)的sqlite數(shù)據(jù)庫連接類,涉及針對(duì)SQLite數(shù)據(jù)庫的連接與增刪改查等sql操作用法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2014-12-12