我的编程空间,编程开发者的网络收藏夹
学习永远不晚

PHP协程与阻塞举例分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

PHP协程与阻塞举例分析

本篇内容介绍了“PHP协程与阻塞举例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

进程、线程、协程

关于进程、线程、协程,有非常详细和丰富的博客或者学习资源,我不在此做赘述,我大致在此介绍一下这几个东西。

  1. 进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。

  2. 线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。

  3. 协程和线程一样共享堆,不共享栈,协程由程序员在协程的代码里显示调度。

PHP中的协程实现基础 yield

yield的根本实现是生成器类,而迭代器类是迭代器接口的实现:

Generator implements Iterator {     public mixed current ( void ) // 返回当前产生的值     public mixed key ( void ) // 返回当前产生的键     public void next ( void ) // 生成器继续执行     public void rewind ( void ) // 重置迭代器,如果迭代已经开始了,这里会抛出一个异常。                                              // renwind的执行将会导致***个yield被执行, 并且忽略了他的返回值.     public mixed send ( mixed $value ) // 向生成器中传入一个值,并且当做 yield 表达式的结果,然后继续执行生成器。如果当这个方法被调用时,生成器                                                // 不在 yield 表达式,那么在传入值之前,它会先运行到***个 yield 表达式。     public void throw ( Exception $exception ) // 向生成器中抛入一个异常     public bool valid ( void ) // 检查迭代器是否被关闭     public void __wakeup ( void ) // 序列化回调,抛出一个异常以表示生成器不能被序列化。 }

自定义简单定时执行任务示例:

(此例子必须依赖于以上鸟哥实现的协程调度代码)

class timer {     private $start = 0; // 定时开始时间     private $timer; // 间隔的时间差,单位秒     private $value = 0; // 产生的结果值     private $callback; // 异步回调     private $isEnd = false; // 当前定时器任务是否结束     public function __construct($timer,callable $callback)     {         $this->start = time();         $this->timer = $timer;         $this->callback = $callback;     }     public function run() {         if($this->valid()) {             $callback = $this->callback;             $callback($this->value ++,$this);             $this->start = time();         }     }          public function valid() {         $end = time();         if($end - $this->start >= $this->timer) {             return true;         } else {             return false;         }     }     public function setEnd($isEnd) {         $this->isEnd = $isEnd;     }     public function getEnd() {         return $this->isEnd;     } }   function taskObject1() {     $timer = new timer(1,function($value,timer $timer) {         if($value >= 5) {             $timer->setEnd(true);         }         echo '<br>'.'A '.$value;     });     $tid = (yield getTaskId());     while (true) {         if($timer->getEnd() == true) {             break;         }         yield $timer->run();     } }  function taskObject2() {     $timer = new timer(2,function($value,timer $timer) {         if($value >= 3) {             $timer->setEnd(true);         }         echo '<br>'.'B '.$value;     });     $tid = (yield getTaskId());     while (true) {         if($timer->getEnd() == true) {             break;         }         yield $timer->run();     } } $scheduler = new Scheduler; $scheduler->newTask(taskObject1()); $scheduler->newTask(taskObject2()); $scheduler->run();

以上实现的是:

  1. 产生两个任务,并行执行,并且给每个任务在执行的时候模拟几秒钟的阻塞;

  2. 让协程切换的时候能顺利切换,其中的任务阻塞不相互影响;

思考:

我为什么要做以上这件事情呢?因为我发现协程实现虽然很强大也很有意思,能让多任务并行,但是我在其中一个任务里调用系统函数 sleep()  的时候,阻塞任务会阻止协程切换,其实从协程的实现原理上来书也是这么回事。

那么,我也就想模拟协程阻塞,但是不产生阻塞看是否可行。PHP本身只提供了生成器为协程调用提供了支撑,如果不依赖扩展,没有提供多线程的程序实现方式,没有java那么强大,可以开子线程进行实现。

我印象中java的子线程是独立执行且不会相互阻塞的,所以我在想,PHP既然可以实现类似于多线程这样的机制,那么能不能实现调用过程中非阻塞呢?

经过这样一个实现和思考,一开始是陷入了一个误区的,是由于PHP原生函数 sleep()  阻塞造成的思维误区,那就是认为要想真正实现非阻塞或者说实现异步的话,是必须依赖于语言底层的。

后来,我想明白了一个道理,既然某个方法或者函数在执行过程中,会产生阻塞,那么把当前这个方法换成自定义的,做成非阻塞(相对于整个协程调度来说)不就行了吗?比如上面的定时执行我自己实现了一个。

而另一方面,协程调度本身的目的也是为了把任务执行过程切成尽量小片,从而快速切换执行,达到并行的目的。从这方面来看,协程应该也算是一种程序设计思想。

以下是一个程序切成尽量小片执行的例子:

// 一个简单的例子 <?php function xrange($start, $end, $step = 1) {     for ($i = $start; $i <= $end; $i += $step) {         yield $i;     } }   foreach (xrange(1, 1000000) as $num) {     echo $num, "\n"; }

这个例子是把原本用 range  生成一个很大的整型数组的方式切换为分片执行,也就是说在遍历的时候再去取到指定的值,从代码上来看,内存消耗相对于之前来说就非常小了。

“PHP协程与阻塞举例分析”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

PHP协程与阻塞举例分析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

PHP协程与阻塞举例分析

本篇内容介绍了“PHP协程与阻塞举例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!进程、线程、协程关于进程、线程、协程,有非常详细和丰富
2023-06-17

php五大io模型之阻塞与非阻塞的示例分析

小编给大家分享一下php五大io模型之阻塞与非阻塞的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!php实现五大io模型-1阻塞与非阻塞阻塞:是指应用程序执行IO操作需要彻底完成后才返回到用户空间非阻塞:是指应用程
2023-06-15

Java9对HTTP2协议支持与非阻塞HTTP API实例分析

这篇文章主要介绍了Java9对HTTP2协议支持与非阻塞HTTP API实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java9对HTTP2协议支持与非阻塞HTTP API实例分析文章都会有所收获,下面
2023-06-29

Node.js的非阻塞I/O、异步与事件驱动实例分析

今天小编给大家分享一下Node.js的非阻塞I/O、异步与事件驱动实例分析的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1、
2023-07-02

Java多线程之多种锁和阻塞队列的示例分析

这篇文章给大家分享的是有关Java多线程之多种锁和阻塞队列的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、悲观锁和乐观锁1.1. 乐观锁顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以
2023-06-15

PHP协程中Go+Chan+Defer的示例分析

这篇文章主要为大家展示了“PHP协程中Go+Chan+Defer的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“PHP协程中Go+Chan+Defer的示例分析”这篇文章吧。Swoole
2023-06-16

低版本Druid连接池+MySQL驱动8.0导致线程阻塞、性能受限的示例分析

这篇文章将为大家详细讲解有关低版本Druid连接池+MySQL驱动8.0导致线程阻塞、性能受限的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。现象应用升级MySQL驱动8.0后,在并发量较高时,查
2023-06-20

RiSearch PHP 搜索引擎的使用流程与实际案例分析

引言:在当今信息爆炸的时代,搜索引擎成为人们获取所需信息的重要工具。而对于网站开发者来说,为网站添加一个高效的搜索引擎是非常必要的。在这篇文章中,我们将介绍一个基于PHP开发的搜索引擎——RiSearch PHP,并通过一个实际案例来展示其
2023-10-21

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录