本文實(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!
我本來(lái)是想讓兩個(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;
}
}
測(cè)試代碼:
?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)簡(jiǎn)單的協(xié)程任務(wù)調(diào)度demo示例