|
导读网页的本质就是超级文本标记语言,通过结合使用其他的Web技术(如:脚本语言、公共网关接口、组件等),可以创造出功能强大的网页。因而,超级文本标记语言是万维网(Web)编程的基础,也就是说万维网是建立... 网页的本质就是超级文本标记语言,通过结合使用其他的Web技术(如:脚本语言、公共网关接口、组件等),可以创造出功能强大的网页。因而,超级文本标记语言是万维网(Web)编程的基础,也就是说万维网是建立在超文本基础之上的。超级文本标记语言之所以称为超文本标记语言,是因为文本中包含了所谓“超级链接”点。 本文先介绍了生成器的概念,重点是yield的用法及生成器的接口。协程部分则简要说了协程的原理,以及PHP协程编程中应当注意的事项。PHP自5.5起引入了生成器(Generator),基于其可实现协程编程。本文先回顾生成器,然后过渡到协程编程。 yield与生成器生成器生成器是一种数据类型,实现了iterator接口。不能通过new得到生成器实例,也没有获取生成器实例的静态方法。得到生成器实例的唯一办法是调用生成器函数(包含yield关键字的函数)。调用生成器函数直接返回一个生成器对象,生成器运行时函数内的代码才开始执行。 先上代码直观感受一下yield与生成器: # generator1.php
function foo() {
exit('exit script when generator runs.');
yield;
}
$gen = foo();
var_dump($gen);
$gen->current();
echo 'unreachable code!';
# 执行结果
object(Generator)#1 (0) {
}
exit script when generator runs.
如其名,生成器可以用来生成数据。只是其生成数据的方式与其他函数不一样:生成器通过 生成器实现了迭代器接口,获取生成器数据可以用 # generator2.php
function foo() {
# 返回键值对数据
yield "key1" => "value1";
$count = 0;
while ($count < 5) {
# 返回值,key自动生成
yield $count;
++ $count;
}
# 不返回值,相当于返回null
yield;
}
# 手动获取生成器数据
$gen = foo();
while ($gen->valid()) {
fwrite(STDOUT, "key:{$gen->key()}, value:{$gen->current()}\n");
$gen->next();
}
# foreach 遍历数据
fwrite(STDOUT, "\ndata from foreach\n");
foreach (foo() as $key => $value) {
fwrite(STDOUT, "key:$key, value:$value\n");
}yield
function logger(string $filename) {
$fd = fopen($filename, 'w+');
while($msg = yield) {
fwrite($fd, date('Y-m-d H:i:s') . ':' . $msg . PHP_EOL);
}
fclose($fd);
}
$logger = logger('log.txt');
$logger->send('program starts!');
// do some thing
$logger->send('program ends!');
其他
总结相对于其他迭代器,生成器具有性能开销小、编码容易的特点。其作用主要体现在三个方面:
关于PHP中的生成器及基本用法,建议看看 2gua 大佬的博文:PHP之生成器,生动有趣且易懂。 协程编程协程(coroutine)是随时可中断、恢复执行的子程序, 进程、线程和协程线程归属于进程,一个进程可有多个线程。进程是计算机分配资源的最小单位,线程是计算机调度执行的最小单位。进程和线程均由操作系统调度。 协程可以看成“用户态的线程”,需要用户程序实现调度。线程和进程由操作系统调度“抢占式”交替运行,协程主动让出CPU“协商式”交替运行。协程十分的轻量,协程切换不涉及线程切换,执行效率高,数目越多,越能体现协程的优势。 生成器和协程生成器实现的协程属于无栈协程(stackless coroutine),即生成器函数只有函数帧,运行时附加到调用方的栈上执行。不同于功能强大的有栈协程(stackful coroutine),生成器暂停后无法控制程序走向,只能将控制权被动的归还调用者;生成器只能中断自身,不能中断整个协程。当然,生成器的好处便是效率高(暂停时只需保存程序计数器即可),实现简单。 协程编程说到PHP中的协程编程,相信大部分人已经看过鸟哥转载(翻译)的这篇博文:在PHP中使用协程实现多任务调度。原文作者 nikic 是PHP的核心开发者,生成器功能的倡议者和实现人。想深入了解生成器及基于其的协程编程,nikic关于生成器的RFC和鸟哥网站上的文章必读。 先看看基于生成器的协程工作方式:协程协作式工作,即协程之间通过主动让出CPU达到多任务交替运行(即并发多任务,但不是并行);一个生成器可看成一个协程,执行到 再来看鸟哥博客理解的难点何在。协程非常轻量,一个系统中可以同时存在成千上万个协程(生成器)。而操作系统不会对协程调度,安排协程执行的工作就落到开发者身上。部分人看不懂鸟哥文章的协程部分,是因为里面说协程编程少(写协程主要就是写生成器函数),而是花笔墨实现了一个协程的调度器(scheduler或者kernel):模拟了操作系统,对所有协程进行公平调度。PHP开发一般的思维是:我写了这些代码,PHP引擎会调用我这些代码得到预期结果。而协程编程不仅要写干活的代码,还要写指导这些代码什么时候干活的代码。没有很好的把握作者的思维,理解起来自然会难一些。需要自行调度,这是生成器协程相对于原生协程(async/await形式)的一个缺点。 知道了协程是怎么回事,那么它能用来干什么?协程自行让出CPU来协作高效利用CPU,让出的时机当然应该是程序阻塞时。什么地方会让程序阻塞呢?用户态的代码鲜有阻塞,阻塞主要是系统调用。而系统调用的大头是IO,所以协程的主要应用场景在网络编程。为了让程序高性能、高并发,程序应该异步执行不能阻塞。既然异步执行,就需要通知和回调,写回调函数避免不了“回调地狱(callback hell)”的问题:代码可读性差,程序执行流程散落在层层回调函数中等。解决回调地狱的方式主要有两种:Promise和协程。协程能以同步的方式编写代码,在高性能网络编程(IO密集型)中是推荐的。 再回过头看PHP中的协程编程。PHP中基于生成器实现实现协程编程,优先推荐使用 如果想用原生态的做PHP协程编程,类似鸟哥博客中的调度器必不可少。调度器调度协程执行,协程中断后控制权又回到调度器中。所以调度器应该总是在主(事件)循环中,即CPU不在执行协程,就应当在执行调度器的代码。无协程运行时,调度器应当自我阻塞避免消耗CPU(鸟哥博客中使用了内置的 总结在协程编程中, 另外需要说明一点,协程和异步没有多大关系,还要看运行环境支撑。常规的PHP运行环境,即使用了promise/coroutine,也还是同步阻塞的。再牛逼的协程框架, 通过生成器和Promise,能实现类似于 相关推荐: PHP中的output_buffering详细介绍,outputbuffering_PHP教程 以上就是php中协程的详细介绍(代码)的详细内容,更多请关注php中文网其它相关文章! 网站建设是一个广义的术语,涵盖了许多不同的技能和学科中所使用的生产和维护的网站。 |
温馨提示:喜欢本站的话,请收藏一下本站!