Dark Frontiers中文网

php基于协程实现异步的方法分析

发布日期:2025-01-04 14:56    点击次数:57

本文实例讲述了php基于协程实现异步的方法。分享给大家供大家参考,具体如下:github上php的协程大部分是根据这篇文章实现的:-multitasking-using-coroutines-in-PHP.html。它们最终的结果都是把回调变成了优雅的顺序执行的代码,但还是阻塞的,不是真正的异步。比如最热门的:https://github.com/recoilphp/recoil先安装:composer require recoil/recoil执行:<?php//recoil.phpinclude __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;}结果:wait start//等待若干秒wait endHelloworld!我本来是想让两个任务并行,结果两个任务变成了串行,中间等待的时间什么事情都干不了。React响应式的编程是严格禁止这种等待的,所以我就参照unity3d的协程自己写了个php版本的。上代码:<?php//Coroutine.php//依赖swoole实现的定时器,也可以用其它方法实现定时器class Coroutine{  //可以根据需要更改定时器间隔,单位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 协程调度]   * @return [type]     [description]   */  public function run()  {    $routine = &$this->routine;    try {      if(!$routine){        return;      }      $value = $routine->current();      //嵌套的协程      if ($value instanceof Generator) {        $this->stack->push($routine);        $routine = $value;        return;      }      //嵌套的协程返回      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;}结果:wait startHelloworld!//等待几秒,但不阻塞wait end希望本文所述对大家PHP程序设计有所帮助。来源:https://blog.csdn.net/llj1985/article/details/51684210

栏目分类



Powered by Dark Frontiers中文网 @2013-2022 RSS地图 HTML地图

Copyright Powered by365建站 © 2013-2024