狂拽酷炫吊炸天 用 PHP 協程實現多工協作

2021-07-22 17:16:18 字數 2350 閱讀 3502

php 5.5 中最重要的特性之一就是對協程( coroutine )和生成器( generator )的支援。生成器的特性已經由官方文件和許多博文(比如這一篇和這一篇)講解得很充分了。另一方面,協程受到的關注則較少。這是因為協程的功能相較而言更加強大,但卻難以講解。

本文會使用協程實現乙個任務排程器,以此幫助你理解協程的概念和用法。我會先用幾個段落做一些介紹。如果你覺得你已經對生成器和協程的基本概念掌握得很牢固了,那麼你可以直接跳至「多工協作」這一段開始閱讀。

生成器背後最原始的想法就是乙個函式不僅僅返回一次資料,而是能夠返回一系列的資料,並且這些資料是挨個返回的。也可以理解為,生成器使你能更方便地實現迭代器。xrange()函式就是乙個生成器的簡單例子:

function

xrange

($start, $end, $step = 1)

}foreach (xrange(1, 1000000) as $num)

上例中的xrange()函式與內建函式range()函式的功能相同。唯一的區別在於range()會返回乙個包含了一百萬個數字的陣列,而xrange()則返回乙個可以吐出這些數字的迭代器,不會去老實地計算出乙個包含所有數字的陣列。

這樣做的好處是顯而易見的。它使得你可以處理超大規模的資料,而無需一次性將它們載入記憶體。你甚至可以處理無窮無盡的資料流。

當然並不是只有生成器能做到這一點,你也可以通過實現乙個iterator介面來完成同樣的工作。生成器只是更加方便,避免你為了生成乙個迭代器而不得不去實現該介面的五個不同方法。

要從對生成器的理解過度到協程的概念,理解它們內部的工作方式是非常重要的:生成器是可中斷的函式,而yield語句則構成了這些中斷點。

接著剛才的例子,當你呼叫xrange(1, 1000000)時,實際上xrange()沒有執行任何**。取而代之地, php 僅返回了乙個generator類的例項,它實現了iterator介面:

$range = xrange(1, 1000000);

var_dump($range); // object(generator)#1

var_dump($range instanceof iterator); // bool(true)

只有當你呼叫 iterator 介面相關的方法時**才會執行。例如,你執行$range->rewind()時,xrange()函式中的**就會執行,直到流程中的第一條yield語句。如此一來,就意味著$i = $startyield $i被執行了。任何傳遞給yield語句的資料都能通過$range->current()來獲取。

你需要呼叫$range->next()方法來繼續執行生成器中的**。這樣它就會繼續執行下去,直到下一條yield語句。所以只要連續地呼叫->next()->current()方法,你就可以從生成器中獲取到所有的返回值,直至最終不再遇到yield語句。對於xrange()函式來說,就是$i超出$end的時候。如此一來,流程會繼續執行完剩餘的**,直至函式的結尾。若此時呼叫->valid()方法則會返回 false ,這個迭代過程就結束了。

相對於上述功能,協程最主要的一點就是加入了向生成器中傳送資料的能力。這使得從生成器到呼叫者的單向資料流,變成了兩者彼此往來的資料通路。

將資料傳遞給協程的方法是呼叫->send()方法,而不是->next()。下面的這個logger()的例子展示了它是如何工作的:

function

logger

($filename)

}$logger = logger(__dir__ . '/log');

$logger->send('foo');

$logger->send('bar');

如你所見,在這裡yield沒有被用作乙個語句,而是作為乙個表示式,也是就說它有乙個返回值。這個返回值是通過->send()語句傳過來的。此例中yield會先返回 'foo' 再返回 'bar'。

吊炸天的 PHP 7 ,你值得擁有

2015年的夏天,雖然來得不算火熱,但是在網際網路技術的夏天,比任何一年都更為火熱。剛剛才結束了 5 月底的網易 支付寶 攜程以及多家雲儲存廠商的接連故障的壞訊息,6月上旬則迎來了程式語言界兩大好訊息,第一件是 swift 2.0 發布以及開源,另一件是 php 7 alpha 版正式發布。這兩件大...

實習第八天 三款炫酷的動畫推薦

最近突然心血來潮,對一些loading感興趣,loading這玩意說重要也重要,說不重要也不重要,因為這是乙個提公升你產品體驗的乙個細節,如果loading做的好,對於一些耗時需要使用者等待的頁面來說會轉移使用者注意力,不會顯得那麼煩躁,所以你可以看到市面上各種各樣好玩的loading動畫,那麼這篇...