php基于协程实现异步的方法分析
发布:smiling 来源: PHP粉丝网 添加日期:2021-12-04 20:35:19 浏览: 评论:0
本文实例讲述了php基于协程实现异步的方法,分享给大家供大家参考,具体如下:
github上php的协程大部分是根据这篇文章实现的:http://nikic.github.io/2012/12/22/Cooperative-multitasking-using-coroutines-in-PHP.html。
它们最终的结果都是把回调变成了优雅的顺序执行的代码,但还是阻塞的,不是真正的异步。
比如最热门的:https://github.com/recoilphp/recoil
先安装:
composer require recoil/recoil
执行:
- <?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;
- }
结果:
- wait start
- //等待若干秒
- wait end
- Hello
- world!
我本来是想让两个任务并行,结果两个任务变成了串行,中间等待的时间什么事情都干不了,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(emptyempty($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 start
- Hello
- world!
- //等待几秒,但不阻塞
- wait end
Tags: php协程 php异步
相关文章
- ·详解php协程知识点(2018-10-19)
- ·PHP中实现异步调用多线程程序代码(2014-08-28)
- ·php Ajax实现异步文件上传的代码(2014-09-08)
- ·PHP异步执行实现的四种方法详解(2015-04-09)
- ·php异步多线程swoole使用实例程序(2015-04-15)
- ·php异步多线程swoole用法实例(2021-04-26)
- ·PHP ajax 异步执行不等待执行结果的处理方法(2021-05-27)
- ·详解PHP实现异步调用的4种方法(2021-07-14)
- ·PHP异步进程助手async-helper(2021-09-02)
- ·php app支付宝回调(异步通知)详解(2021-10-19)
- ·Swoole实现异步投递task任务案例详解(2021-11-14)
- ·PHP扩展Swoole实现实时异步任务队列示例(2021-11-17)
- ·PHP swoole和redis异步任务实现方法分析(2021-12-10)
- ·php基于 swoole 实现的异步处理任务功能示例(2021-12-11)
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)