成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

[轉]:PHP 使用協(xié)同程序實現(xiàn)合作多任務

phoenixsky / 2738人閱讀

摘要:的返回值是傳遞給方法的值。上面的例子演示了基本用法,然而上下文中沒有真正的展示出使用協(xié)程的優(yōu)點。這個時候你應當明白協(xié)程和任務調(diào)度之間的聯(lián)系指令提供了任務中斷自身的一種方法,然后把控制傳遞給調(diào)度器。因此協(xié)程可以運行多個其他任務。

協(xié)程是比較少見的概念,先轉過來作為參考,需要時應該可以用到
轉自:http://www.oschina.net/transl...

生成器

生成器最基本的思想也是一個函數(shù),這個函數(shù)的返回值是依次輸出,而不是只返回一個多帶帶的值?;蛘?,換句話說,生成器使你更方便的實現(xiàn)了迭代器接口。下面通過實現(xiàn)一個xrange函數(shù)來簡單說明:


上面這個xrange()函數(shù)提供了和PHP的內(nèi)建函數(shù)range()一樣的功能。但是不同的是range()函數(shù)返回的是一個包含屬組值從1到100萬的數(shù)組(注:請查看手冊)。而xrange()函數(shù)返回的是依次輸出這些值的一個迭代器,而且并不會真正以數(shù)組形式計算。

這種方法的優(yōu)點是顯而易見的。它可以讓你在處理大數(shù)據(jù)集合的時候不用一次性的加載到內(nèi)存中。甚至你可以處理無限大的數(shù)據(jù)流。

當然,也可以不同通過生成器來實現(xiàn)這個功能,而是可以通過繼承Iterator接口實現(xiàn)。通過使用生成器實現(xiàn)起來會更方便,而不用再去實現(xiàn)iterator接口中的5個方法了。

生成器為可中斷的函數(shù)

要從生成器認識協(xié)同程序,理解它們內(nèi)部是如何工作的非常重要:生成器是可中斷的函數(shù),在它里面,yield構成了中斷點。?

緊接著上面的例子,如果你調(diào)用xrange(1,1000000)的話,xrange()函數(shù)里代碼沒有真正地運行。相反,PHP只是返回了一個實現(xiàn)了迭代器接口的 生成器類實例:?


?

?

?

協(xié)程

協(xié)程給上面功能添加的主要東西是回送數(shù)據(jù)給生成器的能力。這將把生成器到調(diào)用者的單向通信轉變?yōu)閮烧咧g的雙向通信。

?

send("Foo");
$logger->send("Bar")

正如你能看到,這兒yield沒有作為一個語句來使用,而是用作一個表達式。即它有一個返回值。yield的返回值是傳遞給send()方法的值。 在這個例子里,yield將首先返回"Foo",然后返回"Bar"。

上面的例子里yield僅作為接收者?;旌蟽煞N用法是可能的,即既可接收也可發(fā)送。接收和發(fā)送通信如何進行的例子如下:

current());    // string(6) "yield1"
var_dump($gen->send("ret1")); // string(4) "ret1"   (the first var_dump in gen)
                              // string(6) "yield2" (the var_dump of the ->send() return value)
var_dump($gen->send("ret2")); // string(4) "ret2"   (again from within gen)
                              // NULL               (the return value of ->send())

多任務協(xié)作

如果閱讀了上面的logger()例子,那么你認為“為了雙向通信我為什么要使用協(xié)程呢? 為什么我不能只用常見的類呢?”,你這么問完全正確。上面的例子演示了基本用法,然而上下文中沒有真正的展示出使用協(xié)程的優(yōu)點。這就是列舉許多協(xié)程例子的理由。正如上面介紹里提到的,協(xié)程是非常強大的概念,不過這樣的應用很稀少而且常常十分復雜。給出一些簡單而真實的例子很難。

多任務協(xié)作這個術語中的“協(xié)作”說明了如何進行這種切換的:它要求當前正在運行的任務自動把控制傳回給調(diào)度器,這樣它就可以運行其他任務了。這與“搶占”多任務相反,搶占多任務是這樣的:調(diào)度器可以中斷運行了一段時間的任務,不管它喜歡還是不喜歡。協(xié)作多任務在Windows的早期版本(windows95)和Mac OS中有使用,不過它們后來都切換到使用搶先多任務了。理由相當明確:如果你依靠程序自動傳回 控制的話,那么壞行為的軟件將很容易為自身占用整個CPU,不與其他任務共享。?

這個時候你應當明白協(xié)程和任務調(diào)度之間的聯(lián)系:yield指令提供了任務中斷自身的一種方法,然后把控制傳遞給調(diào)度器。因此協(xié)程可以運行多個其他任務。更進一步來說,yield可以用來在任務和調(diào)度器之間進行通信。

我們的目的是 對 “任務”用更輕量級的包裝的協(xié)程函數(shù):

taskId = $taskId;
        $this->coroutine = $coroutine;
    }

    public function getTaskId() {
        return $this->taskId;
    }

    public function setSendValue($sendValue) {
        $this->sendValue = $sendValue;
    }

    public function run() {
        if ($this->beforeFirstYield) {
            $this->beforeFirstYield = false;
            return $this->coroutine->current();
        } else {
            $retval = $this->coroutine->send($this->sendValue);
            $this->sendValue = null;
            return $retval;
        }
    }

    public function isFinished() {
        return !$this->coroutine->valid();
    }
}

?

任務ID標記

send("something"));

// As the send() happens before the first yield there is an implicit rewind() call,
// so what really happens is this:
$gen->rewind();
var_dump($gen->send("something"));

// The rewind() will advance to the first yield (and ignore its value), the send() will
// advance to the second yield (and dump its value). Thus we loose the first yielded value!

調(diào)度器現(xiàn)在不得不比多任務循環(huán)要做稍微多點了,然后才運行多任務:

 task
    protected $taskQueue;

    public function __construct() {
        $this->taskQueue = new SplQueue();
    }

    public function newTask(Generator $coroutine) {
        $tid = ++$this->maxTaskId;
        $task = new Task($tid, $coroutine);
        $this->taskMap[$tid] = $task;
        $this->schedule($task);
        return $tid;
    }

    public function schedule(Task $task) {
        $this->taskQueue->enqueue($task);
    }

    public function run() {
        while (!$this->taskQueue->isEmpty()) {
            $task = $this->taskQueue->dequeue();
            $task->run();

            if ($task->isFinished()) {
                unset($this->taskMap[$task->getTaskId()]);
            } else {
                $this->schedule($task);
            }
        }
    }
}

?

?

newTask(task1());
$scheduler->newTask(task2());

$scheduler->run();
This is task 1 iteration 1.
This is task 2 iteration 1.
This is task 1 iteration 2.
This is task 2 iteration 2.
This is task 1 iteration 3.
This is task 2 iteration 3.
This is task 1 iteration 4.
This is task 2 iteration 4.
This is task 1 iteration 5.
This is task 2 iteration 5.
This is task 1 iteration 6.
This is task 1 iteration 7.
This is task 1 iteration 8.
This is task 1 iteration 9.
This is task 1 iteration 10.
與調(diào)度器之間通信?

既然調(diào)度器已經(jīng)運行了,那么我們就轉向日程表的下一項:任務和調(diào)度器之間的通信。我們將使用進程用來和操作系統(tǒng)會話的同樣的方式來通信:系統(tǒng)調(diào)用。我們需要系統(tǒng)調(diào)用的理由是操作系統(tǒng)與進程相比它處在不同的權限級別上。因此為了執(zhí)行特權級別的操作(如殺死另一個進程),就不得不以某種方式把控制傳回給內(nèi)核,這樣內(nèi)核就可以執(zhí)行所說的操作了。再說一遍,這種行為在內(nèi)部是通過使用中斷指令來實現(xiàn)的。過去使用的是通用的int指令,如今使用的是更特殊并且更快速的syscall/sysenter指令。

為了說明系統(tǒng)調(diào)用,我將對可調(diào)用的系統(tǒng)調(diào)用做一個小小的封裝:

callback = $callback;
    }

    public function __invoke(Task $task, Scheduler $scheduler) {
        $callback = $this->callback; // Can"t call it directly in PHP :/
        return $callback($task, $scheduler);
    }
}
taskQueue->isEmpty()) {
        $task = $this->taskQueue->dequeue();
        $retval = $task->run();

        if ($retval instanceof SystemCall) {
            $retval($task, $this);
            continue;
        }

        if ($task->isFinished()) {
            unset($this->taskMap[$task->getTaskId()]);
        } else {
            $this->schedule($task);
        }
    }
}
setSendValue($task->getTaskId());
        $scheduler->schedule($task);
    });
}
newTask(task(10));
$scheduler->newTask(task(5));

$scheduler->run();
setSendValue($scheduler->newTask($coroutine));
            $scheduler->schedule($task);
        }
    );
}

function killTask($tid) {
    return new SystemCall(
        function(Task $task, Scheduler $scheduler) use ($tid) {
            $task->setSendValue($scheduler->killTask($tid));
            $scheduler->schedule($task);
        }
    );
}

?killTask函數(shù)需要在調(diào)度器里增加一個方法:

taskMap[$tid])) {
        return false;
    }

    unset($this->taskMap[$tid]);

    // This is a bit ugly and could be optimized so it does not have to walk the queue,
    // but assuming that killing tasks is rather rare I won"t bother with it now
    foreach ($this->taskQueue as $i => $task) {
        if ($task->getTaskId() === $tid) {
            unset($this->taskQueue[$i]);
            break;
        }
    }

    return true;
}
newTask(task());
$scheduler->run();

?這段代碼將打印以下信息:

Parent task 1 iteration 1.
Child task 2 still alive!
Parent task 1 iteration 2.
Child task 2 still alive!
Parent task 1 iteration 3.
Child task 2 still alive!
Parent task 1 iteration 4.
Parent task 1 iteration 5.
Parent task 1 iteration 6.

文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://systransis.cn/yun/30562.html

相關文章

  • Google發(fā)布Anthos:宣告集群云Kubernetes時代已來

    摘要:今天,大會召開,在這場規(guī)模三萬人的盛會上,宣布推出作為多云服務新方案,提供跨云目前僅支持和管理集群。是業(yè)界第一個多集群多云管理平臺。正如發(fā)布而極大地幫助普及了技術一樣,我們也相信將促進將多集群多云管理帶入更主流的階段。 今天, Google Cloud NEXT 2019大會召開,在這場規(guī)模三萬人的盛會上,G...

    mindwind 評論0 收藏0
  • 干貨 | PHP就該這么學!

    摘要:梳理之后,目標就會被分解成一個個需要完成的具體任務。勤學學習效率與效果取決于執(zhí)行力。這種選手即便幫他解決了問題,他也學不到東西。拆分任務將目標分解成具體可執(zhí)行的學習任務。搜集知識資源查閱官方文檔購買書籍搜集網(wǎng)絡干貨文章。 前段時間和大家一起分享了一篇關于學習方法內(nèi)容《大牛與搬運工的差距——學習方法的力量》。我們將學習過程分成八步,并借鑒了敏捷開發(fā)的迭代思想,以達到自我迭代學習的效果。行...

    wushuiyong 評論0 收藏0
  • es6 Generators詳解

    摘要:每個任務必須顯式地掛起自己,在任務切換發(fā)生時給予它完全的控制。在這些嘗試中,數(shù)據(jù)經(jīng)常在任務之間共享。但由于明確的暫停,幾乎沒有風險。 翻譯自 github 概述 什么是generators? 我們可以把generators理解成一段可以暫停并重新開始執(zhí)行的函數(shù) function* genFunc() { // (A) console.log(First); yi...

    zhaot 評論0 收藏0
  • 】深入理解PHP之:Nginx 與 FPM 的工作機制

    摘要:要說與是如何協(xié)同工作的,首先得說和這兩個協(xié)議。是與后臺語言交互的協(xié)議,有了這個協(xié)議,開發(fā)者可以使用任何語言處理發(fā)來的請求,動態(tài)的生成內(nèi)容。為了能夠使理解協(xié)議,提供了模塊來將請求映射為對應的請求。如此以來,與通信的整個流程應該比較清晰了吧。 【原文地址】https://zhuanlan.zhihu.com/p/... 網(wǎng)絡上有很多關于如何配置 Nginx + FPM 的文章,但它們更多從...

    meteor199 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<