PHP中使用協(xié)同程序實現(xiàn)合作多任務第1/2頁(2)_PHP教程

      編輯Tag賺U幣
      教程Tag:暫無Tag,歡迎添加,賺取U幣!

      推薦:PHP中使用協(xié)同程序實現(xiàn)合作多任務
      PHP5.5一個比較好的新功能是實現(xiàn)對生成器和協(xié)同程序的支持。對于生成器,PHP的文檔和各種其他的博客文章(就像這一個或這一個)已經(jīng)有了非常詳細的講解。協(xié)同程序相對受到的關注就少了,所以協(xié)同程序雖然有很強大的功能但也很難被知曉,解釋起來也比較困難。 這篇文章

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

      在這篇文章里,我決定去做的是使用協(xié)程實現(xiàn)多任務協(xié)作。我們盡力解決的問題是你想并發(fā)地運行多任務(或者“程序”)。不過處理器在一個時刻只能運行 一個任務(這篇文章的目標是不考慮多核的)。因此處理器需要在不同的任務之間進行切換,而且總是讓每個任務運行 “一小會兒”。 

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

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

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

      復制代碼 代碼如下:
      <?php

      class Task {
          protected $taskId;
          protected $coroutine;
          protected $sendValue = null;
          protected $beforeFirstYield = true;

          public function __construct($taskId, Generator $coroutine) {
              $this->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標記一個協(xié)程。使用setSendValue()方法,你可以指定哪些值將被發(fā)送到下次的恢復(在之后你會了解到我們需要這個)。 run()函數(shù)確實沒有做什么,除了調用send()方法的協(xié)同程序。要理解為什么添加beforeFirstYieldflag,需要考慮下面的代碼片 段:

      復制代碼 代碼如下:
      <?php

      function gen() {
          yield 'foo';
          yield 'bar';
      }

      $gen = gen();
      var_dump($gen->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!

      通過添加 beforeFirstYieldcondition 我們可以確定 first yield 的值 被返回。 

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

      復制代碼 代碼如下:
      <?php

      class Scheduler {
          protected $maxTaskId = 0;
          protected $taskMap = []; // taskId => 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);
          }

      分享:php修改NetBeans默認字體的大小
      在Netbeans中由于使用了Swing進行開發(fā),所以其中界面的字體也是由Java虛擬機進行配置而不是隨操作系統(tǒng)的。在安裝完Netbeans后默認的字體大小是11px。而在Windows下的宋體最小支持12px。所以字體為11px就已經(jīng)無法完整顯示了。 簡單的解決辦法就是將字體改大一點。詳細的

      來源:模板無憂//所屬分類:PHP教程/更新時間:2013-07-04
      相關PHP教程