php实现协程,真正的异步
来源:互联网 发布:吉林破获特大网络诈骗 编辑:程序博客网 时间:2024/05/29 06:51
php实现协程,真正的异步
2016-06-15 18:43 1454人阅读 评论(1)收藏举报
分类:
版权声明:本文为博主原创文章,未经博主允许不得转载。
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
0 0
- php实现协程,真正的异步
- php实现协程,真正的异步
- php实现协程,真正的异步
- PHP 观察者模式 的真正实现
- 基于swoole扩展实现真正的PHP数据库连接池
- 基于swoole扩展实现真正的PHP数据库连接池
- PHP curl实现异步的http请求
- 关于PHP实现异步操作的研究
- HandlerThread实现真正的异步的简单实例,用到了Bundle对象
- php实现异步操作
- php实现异步处理
- PHP异步实现
- 【PHP】PHP实现简单的setTimeOut来完成异步延时
- 【Android单元测试系列】真正的异步单元测试
- 真正的 Tornado 异步非阻塞
- PHP 真正多线程的使用
- PHP 真正多线程的使用
- PHP 真正多线程的使用
- 图像处理中滤波(filtering)与卷积(convolution)的区别
- 杭电2025
- 正向代理,反向代理和透明代理的原理和区别!
- iOS开发UI篇—核心动画(关键帧动画)
- java JVM 运行时数据区
- php实现协程,真正的异步
- thinkphp图片拖动验证码
- iOS Widget快速浏览页面的创建以及证书添加标识符
- Task&Activity&ActivityRecord...
- uboot的移植2-从uboot官方标准uboot开始移植
- ZOJ 2314 Reactor Cooling
- Android内存优化工具(三)MAT
- iOS开发UI篇—核心动画(转场动画和组动画)
- android studio开发手机状态栏颜色更改