PHP協程內容的詳解

來源:互聯網
上載者:User
這篇文章給大家分享了關於php協成的內容,有一定的參考價值,希望可以協助到有需要的朋友。

概念

咱們知道多進程和多線程是實現並發的有效方式。但多進程的環境切換資源開銷太大;多線程開銷相比要小很多,也是現在主流的做法,但其的控制權在核心,從而使使用者(程式員)失去了對代碼的控制,而且線程的環境切換也是有一定開銷的。 這時為瞭解決以上問題,"協程"(coroutine)的概念就產生了。你可以將協程理解為更輕量級的線程。這種線程叫做“使用者空間線程“。協程,有下面兩個特點:

  1. 協同。因為是由程式員自己寫的調度策略,其通過協作而不是搶佔來進行切換

  2. 在使用者態完成建立,切換和銷毀

PHP對協程的支援是在迭代產生器的基礎上, 增加了可以回送資料給產生器的功能(調用者發送資料給被調用的產生器函數)。 這就把產生器到調用者的單向通訊轉變為兩者之間的雙向通訊。

迭代器

迭代器的概念這裡就不贅述了。下面看看我們自己實現的一個迭代器。

class MyIterator implements Iterator{    private $var = array();    public function __construct($array)    {        if (is_array($array)) {            $this->var = $array;        }    }    public function rewind() {   // 第一次迭代時候會執行(或調用該方法的時候),後面的迭代將不會執行。        echo "rewinding\n";        reset($this->var);      }    public function current() {        $var = current($this->var);        echo "current: $var\n";        return $var;    }    public function key() {        $var = key($this->var);        echo "key: $var\n";        return $var;    }    public function next() {    // 最後執行,就是執行完下面sleep(2)後再執行。(執行了next本次迭代才算結束)        $var = next($this->var);        echo "next: $var\n";        return $var;    }    public function valid() {      // 當valid返回false的時候迭代結束        $var = $this->current() !== false;        echo "valid: {$var}\n";        return $var;    }}$values = array(1,2,3,4);$it = new MyIterator($values);foreach ($it as $a => $b) { // 進行迭代(每次迭代,會依次執行以下方法: rewind(特別之處見上面解釋), valid, current, key, next)    print "=====\n";    sleep(2);}

輸出:

rewindingcurrent: 1  // 因為valid裡面調用了current, 這裡current出來一次valid: 1current: 1key: 0=====next: 2current: 2valid: 1current: 2key: 1=====next: 3current: 3valid: 1current: 3key: 2=====next: 4current: 4valid: 1current: 4key: 3=====next: current: valid:    // valid返回false,迭代結束

產生器

有了yeild的方法就是一個產生器(產生器實現了Iterator介面,即一個產生器有迭代器的特點)。產生器的實現如下:

function xrange($start, $end, $step = 1) {    for ($i = $start; $i <= $end; $i += $step) {        echo $i . "\n";        yield;    }}// foreach方式foreach (xrange(1, 10) as $num) {    }$gene = xrange(1, 10); // gene就是一個產生器對象// current$gene->current();  // 列印1// next$gene->next();$gene->current()  // 列印2

輸出:

1234567891012

產生器各方法詳解可看文檔: http://php.net/manual/zh/class.generator.php

注意:

產生器不能像函數一樣直接調用,調用方法如下:

1. foreach他

2. send($value)

3. current / next...

yield

yield的文法很靈活,我們用下面的例子,讓大家能明白yield文法的使用。

用例1: 讓出cpu執行權

function task1 () {for ($i = 1; $i <= 10; ++$i) {        echo "This is task 1 iteration $i.\n";        yield;// 遇到yield就會主動讓出CPU的執行權;    }}$a = task1(); $a->current(); // 執行第一次迭代$a->send(1);  // 喚醒當時讓出CPU執行權的yield

輸出:

This is task 1 iteration 1.This is task 1 iteration 2.

用例2: yield的返回

// yield返回function task2 () {    for ($i = 1; $i <= 10; ++$i) {            echo "This is task 2 iteration $i.\n";            yield "lm$i";  // 遇到yield就會主動讓出CPU的執行權,for暫停執行, 然後返回"lm"。放在yield後面的值就是傳回值        }}$a = task2(); $res = $a->current();  // 第一次迭代, 遇到yield返回var_dump($res);  $res = $a->send(1);  // 喚醒yield, for繼續執行,遇到yield返回。var_dump($res);

輸出:

This is task 2 iteration 1.string(3) "lm1"This is task 2 iteration 2.string(3) "lm2"

用例3: yield接收值

function task3 () {    for ($i = 1; $i <= 10; ++$i) {            echo "This is task 3 iteration $i.\n";            $getValue = yield;// 遇到yield就會主動讓出CPU的執行權;send後,將send值賦值給getValue            echo $getValue . " ";        }}$a = task3(); $a->current();$a->send("aa");  // 喚醒yield,並將"aa"值賦值給$getValue變數

輸出:

This is task 3 iteration 1.aa This is task 3 iteration 2.

用例4: yeild接收和返回寫在一起

function task4 () {    for ($i = 1; $i <= 10; ++$i) {        echo "This is task 4 iteration $i.\n";        $ret = yield "lm$i";  // yield, 然後返回lm$i; 當send時,將send過來的值賦值給$ret;        echo $ret;    }}$a = task4(); var_dump($a->current());     // 返回lm1var_dump($a->send("hhh "));  // 先喚醒yield, 將"hhh "賦值給$ret,再返回lm2var_dump($a->send("www "));  // 先喚醒yield, 將"www "賦值給$ret,再返回lm3

輸出:

This is task 4 iteration 1.string(3) "lm1"hhh This is task 4 iteration 2. string(3) "lm2"www  This is task 4 iteration 3. string(3) "lm3"
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.