

php实现协程,真正的异步
source link: https://blog.p2hp.com/archives/4275
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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(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 start
Hello
world!
//等待几秒,但不阻塞
wait end
注:此文章需要验证。
来自 http://m.blog.csdn.net/article/details?id=51684210
Recommend
-
87
协程定义: 协程,又称微线程,纤程。英文名Coroutine。 子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在执行过程中又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕。所以子程序调用是通过栈实现的,一个线程就是执行一个子程序。子...
-
30
欢迎回来! 距离上一篇博客已经接近一年了,在这期间虽然也有一些奇怪的研究,但是都还没有到达能够写博客的地步。每天都在为琐事和业务代码忙忙碌碌,也没有闲工夫去研究比较有意思的东西。这也算是我给懒癌找的借口,不过还是...
-
28
青_雉2020.01.22 20:55:20字数 664阅读 502书接上回,我们一起体验了reactor模式,也了解到了其解决什么场景下的问题。 我们将一同感受...
-
13
The Coroutine in C++ 20 协程与异步薛定谔的喵一个人NB的不是标签这是我研究C++ Cor...
-
8
在PHP中使用协程实现多任务调度 本文地址: https://www.laruence.com/2015/05/28/3038.html 转载请注明出处
-
11
先说一些废话 PHP 5.5 以来,新的诸多特性又一次令 PHP 焕发新的光彩,虽然在本文写的时候已是 PHP 7 alpha 2 发布后的一段时间,但此时国内依旧是 php 5.3 的天下。不过我认为新的特性迟早会因为旧的版本的逐渐消失而变得越发重要,尤其是 PHP 7 的正...
-
5
使用 algebraic effect 实现协程和异步IO2021-10-09最近的几篇博客都是关于 algebraic effect 的,主要是我发现这东西像发现宝了。它可以像 call/cc 一样强大,而又不至于太过失控。基于 algebraic effect 可以实现好多种其它的 f...
-
14
Feb 10, 2017实现 PHP 协程需要了解的基本内容。 多进程/线程最早的服务器端程序都是通过多进程、多线程来解决并发IO的问题。进程模型出现的最早,从Unix 系统诞生就开始有了进程的概念。最早的服务器端程序一般都是 Accept 一个客...
-
8
异步 PHP — 多进程、多线程和协程 让我们看一下这段典型的 PHP 代码: function names() { $data = Http::get('data.location/products')-&...
-
9
很古老的用法了,现在大多用的aiohttp库实现,这篇记录仅仅用做个人的协程底层实现的学习。 争取用看得懂的字来描述问题。 1.什么是yield 如果还没有怎么用过的话,直接把yield看做成一种特殊的return(PS:本质 generator(...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK