|
導讀網(wǎng)頁的本質(zhì)就是超級文本標記語言,通過結(jié)合使用其他的Web技術(shù)(如:腳本語言、公共網(wǎng)關(guān)接口、組件等),可以創(chuàng)造出功能強大的網(wǎng)頁。因而,超級文本標記語言是萬維網(wǎng)(Web)編程的基礎(chǔ),也就是說萬維網(wǎng)是建立... 網(wǎng)頁的本質(zhì)就是超級文本標記語言,通過結(jié)合使用其他的Web技術(shù)(如:腳本語言、公共網(wǎng)關(guān)接口、組件等),可以創(chuàng)造出功能強大的網(wǎng)頁。因而,超級文本標記語言是萬維網(wǎng)(Web)編程的基礎(chǔ),也就是說萬維網(wǎng)是建立在超文本基礎(chǔ)之上的。超級文本標記語言之所以稱為超文本標記語言,是因為文本中包含了所謂“超級鏈接”點。 本文先介紹了生成器的概念,重點是yield的用法及生成器的接口。協(xié)程部分則簡要說了協(xié)程的原理,以及PHP協(xié)程編程中應當注意的事項。PHP自5.5起引入了生成器(Generator),基于其可實現(xiàn)協(xié)程編程。本文先回顧生成器,然后過渡到協(xié)程編程。 yield與生成器生成器生成器是一種數(shù)據(jù)類型,實現(xiàn)了iterator接口。不能通過new得到生成器實例,也沒有獲取生成器實例的靜態(tài)方法。得到生成器實例的唯一辦法是調(diào)用生成器函數(shù)(包含yield關(guān)鍵字的函數(shù))。調(diào)用生成器函數(shù)直接返回一個生成器對象,生成器運行時函數(shù)內(nèi)的代碼才開始執(zhí)行。 先上代碼直觀感受一下yield與生成器: # generator1.php
function foo() {
exit('exit script when generator runs.');
yield;
}
$gen = foo();
var_dump($gen);
$gen->current();
echo 'unreachable code!';
# 執(zhí)行結(jié)果
object(Generator)#1 (0) {
}
exit script when generator runs.
如其名,生成器可以用來生成數(shù)據(jù)。只是其生成數(shù)據(jù)的方式與其他函數(shù)不一樣:生成器通過 生成器實現(xiàn)了迭代器接口,獲取生成器數(shù)據(jù)可以用 # generator2.php
function foo() {
# 返回鍵值對數(shù)據(jù)
yield "key1" => "value1";
$count = 0;
while ($count < 5) {
# 返回值,key自動生成
yield $count;
++ $count;
}
# 不返回值,相當于返回null
yield;
}
# 手動獲取生成器數(shù)據(jù)
$gen = foo();
while ($gen->valid()) {
fwrite(STDOUT, "key:{$gen->key()}, value:{$gen->current()}\n");
$gen->next();
}
# foreach 遍歷數(shù)據(jù)
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!');
其他
總結(jié)相對于其他迭代器,生成器具有性能開銷小、編碼容易的特點。其作用主要體現(xiàn)在三個方面:
關(guān)于PHP中的生成器及基本用法,建議看看 2gua 大佬的博文:PHP之生成器,生動有趣且易懂。 協(xié)程編程協(xié)程(coroutine)是隨時可中斷、恢復執(zhí)行的子程序, 進程、線程和協(xié)程線程歸屬于進程,一個進程可有多個線程。進程是計算機分配資源的最小單位,線程是計算機調(diào)度執(zhí)行的最小單位。進程和線程均由操作系統(tǒng)調(diào)度。 協(xié)程可以看成“用戶態(tài)的線程”,需要用戶程序?qū)崿F(xiàn)調(diào)度。線程和進程由操作系統(tǒng)調(diào)度“搶占式”交替運行,協(xié)程主動讓出CPU“協(xié)商式”交替運行。協(xié)程十分的輕量,協(xié)程切換不涉及線程切換,執(zhí)行效率高,數(shù)目越多,越能體現(xiàn)協(xié)程的優(yōu)勢。 生成器和協(xié)程生成器實現(xiàn)的協(xié)程屬于無棧協(xié)程(stackless coroutine),即生成器函數(shù)只有函數(shù)幀,運行時附加到調(diào)用方的棧上執(zhí)行。不同于功能強大的有棧協(xié)程(stackful coroutine),生成器暫停后無法控制程序走向,只能將控制權(quán)被動的歸還調(diào)用者;生成器只能中斷自身,不能中斷整個協(xié)程。當然,生成器的好處便是效率高(暫停時只需保存程序計數(shù)器即可),實現(xiàn)簡單。 協(xié)程編程說到PHP中的協(xié)程編程,相信大部分人已經(jīng)看過鳥哥轉(zhuǎn)載(翻譯)的這篇博文:在PHP中使用協(xié)程實現(xiàn)多任務調(diào)度。原文作者 nikic 是PHP的核心開發(fā)者,生成器功能的倡議者和實現(xiàn)人。想深入了解生成器及基于其的協(xié)程編程,nikic關(guān)于生成器的RFC和鳥哥網(wǎng)站上的文章必讀。 先看看基于生成器的協(xié)程工作方式:協(xié)程協(xié)作式工作,即協(xié)程之間通過主動讓出CPU達到多任務交替運行(即并發(fā)多任務,但不是并行);一個生成器可看成一個協(xié)程,執(zhí)行到 再來看鳥哥博客理解的難點何在。協(xié)程非常輕量,一個系統(tǒng)中可以同時存在成千上萬個協(xié)程(生成器)。而操作系統(tǒng)不會對協(xié)程調(diào)度,安排協(xié)程執(zhí)行的工作就落到開發(fā)者身上。部分人看不懂鳥哥文章的協(xié)程部分,是因為里面說協(xié)程編程少(寫協(xié)程主要就是寫生成器函數(shù)),而是花筆墨實現(xiàn)了一個協(xié)程的調(diào)度器(scheduler或者kernel):模擬了操作系統(tǒng),對所有協(xié)程進行公平調(diào)度。PHP開發(fā)一般的思維是:我寫了這些代碼,PHP引擎會調(diào)用我這些代碼得到預期結(jié)果。而協(xié)程編程不僅要寫干活的代碼,還要寫指導這些代碼什么時候干活的代碼。沒有很好的把握作者的思維,理解起來自然會難一些。需要自行調(diào)度,這是生成器協(xié)程相對于原生協(xié)程(async/await形式)的一個缺點。 知道了協(xié)程是怎么回事,那么它能用來干什么?協(xié)程自行讓出CPU來協(xié)作高效利用CPU,讓出的時機當然應該是程序阻塞時。什么地方會讓程序阻塞呢?用戶態(tài)的代碼鮮有阻塞,阻塞主要是系統(tǒng)調(diào)用。而系統(tǒng)調(diào)用的大頭是IO,所以協(xié)程的主要應用場景在網(wǎng)絡編程。為了讓程序高性能、高并發(fā),程序應該異步執(zhí)行不能阻塞。既然異步執(zhí)行,就需要通知和回調(diào),寫回調(diào)函數(shù)避免不了“回調(diào)地獄(callback hell)”的問題:代碼可讀性差,程序執(zhí)行流程散落在層層回調(diào)函數(shù)中等。解決回調(diào)地獄的方式主要有兩種:Promise和協(xié)程。協(xié)程能以同步的方式編寫代碼,在高性能網(wǎng)絡編程(IO密集型)中是推薦的。 再回過頭看PHP中的協(xié)程編程。PHP中基于生成器實現(xiàn)實現(xiàn)協(xié)程編程,優(yōu)先推薦使用 如果想用原生態(tài)的做PHP協(xié)程編程,類似鳥哥博客中的調(diào)度器必不可少。調(diào)度器調(diào)度協(xié)程執(zhí)行,協(xié)程中斷后控制權(quán)又回到調(diào)度器中。所以調(diào)度器應該總是在主(事件)循環(huán)中,即CPU不在執(zhí)行協(xié)程,就應當在執(zhí)行調(diào)度器的代碼。無協(xié)程運行時,調(diào)度器應當自我阻塞避免消耗CPU(鳥哥博客中使用了內(nèi)置的 總結(jié)在協(xié)程編程中, 另外需要說明一點,協(xié)程和異步?jīng)]有多大關(guān)系,還要看運行環(huán)境支撐。常規(guī)的PHP運行環(huán)境,即使用了promise/coroutine,也還是同步阻塞的。再牛逼的協(xié)程框架, 通過生成器和Promise,能實現(xiàn)類似于 相關(guān)推薦: PHP中的output_buffering詳細介紹,outputbuffering_PHP教程 以上就是php中協(xié)程的詳細介紹(代碼)的詳細內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章! 網(wǎng)站建設(shè)是一個廣義的術(shù)語,涵蓋了許多不同的技能和學科中所使用的生產(chǎn)和維護的網(wǎng)站。 |
溫馨提示:喜歡本站的話,請收藏一下本站!