PHP中使用协同程序实现合作多任务(5)_PHP教程

编辑Tag赚U币
教程Tag:暂无Tag,欢迎添加,赚取U币!

推荐:php修改NetBeans默认字体的大小
在Netbeans中由于使用了Swing进行开发,所以其中界面的字体也是由Java虚拟机进行配置而不是随操作系统的。在安装完Netbeans后默认的字体大小是11px。而在Windows下的宋体最小支持12px。所以字体为11px就已经无法完整显示了。 简单的解决办法就是将字体改大一点。详细的

这段代码将打印以下信息:

复制代码 代码如下:
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.

经过三次迭代以后子任务将被杀死,因此这就是"Child is still alive"消息结束的时候。可能应当指出的是这不是真正的父子关系。 因为甚至在父任务结束后子任务仍然可以运行。或者子任务可以杀死父任务。可以修改调度器使它具有更层级化的任务结构,不过 在这篇文章里我没有这么做。 

你可以实现许多进程管理调用。例如 wait(它一直等待到任务结束运行时),exec(它替代当前任务)和fork(它创建一个 当前任务的克隆)。fork非常酷,而且你可以使用PHP的协程真正地实现它,因为它们都支持克隆。 

然而让我们把这些留给有兴趣的读者吧,我们去看下一个议题。

几点人
翻译于 4天前
0人顶
顶 翻译的不错哦!
 

非阻塞IO
很明显,我们的任务管理系统的真正很酷的应用是web服务器。它有一个任务是在套接字上侦听是否有新连接,当有新连接要建立的时候  ,它创建一个新任务来处理新连接。
 web服务器最难的部分通常是像读数据这样的套接字操作是阻塞的。例如PHP将等待到客户端完成发送为止。对一个WEB服务器来说,这 根本不行;这就意味着服务器在一个时间点上只能处理一个连接。

解决方案是确保在真正对套接字读写之前该套接字已经“准备就绪”。为了查找哪个套接字已经准备好读或者写了,可以使用 流选择函数。 

首先,让我们添加两个新的 syscall,它们将等待直到指定 socket 准备好:

复制代码 代码如下:
 <?php     
 function waitForRead($socket) { 
     return new SystemCall( 
         function(Task $task, Scheduler $scheduler) use ($socket) { 
             $scheduler->waitForRead($socket, $task); 
         } 
     ); 
 } 

 function waitForWrite($socket) { 
     return new SystemCall( 
         function(Task $task, Scheduler $scheduler) use ($socket) { 
             $scheduler->waitForWrite($socket, $task); 
         } 
     ); 
 }
这些 syscall 只是在调度器中代理其各自的方法:  复制代码 代码如下:
 <?php 

 // resourceID => [socket, tasks] 
 protected $waitingForRead = []; 
 protected $waitingForWrite = []; 

 public function waitForRead($socket, Task $task) { 
     if (isset($this->waitingForRead[(int) $socket])) { 
         $this->waitingForRead[(int) $socket][1][] = $task; 
     } else { 
         $this->waitingForRead[(int) $socket] = [$socket, [$task]]; 
     } 
 } 

 public function waitForWrite($socket, Task $task) { 
     if (isset($this->waitingForWrite[(int) $socket])) { 
         $this->waitingForWrite[(int) $socket][1][] = $task; 
     } else { 
         $this->waitingForWrite[(int) $socket] = [$socket, [$task]]; 
     } 
 }
 
waitingForRead 及 waitingForWrite 属性是两个承载等待的socket 及等待它们的任务的数组。有趣的部分在于下面的方法,它将检查 socket 是否可用,并重新安排各自任务: 复制代码 代码如下:
 <?php 

 protected function ioPoll($timeout) { 
     $rSocks = []; 
     foreach ($this->waitingForRead as list($socket)) { 
         $rSocks[] = $socket; 
     } 

     $wSocks = []; 
     foreach ($this->waitingForWrite as list($socket)) { 
         $wSocks[] = $socket; 
     } 

     $eSocks = []; // dummy 

     if (!stream_select($rSocks, $wSocks, $eSocks, $timeout)) { 
         return; 
     } 

     foreach ($rSocks as $socket) { 
         list(, $tasks) = $this->waitingForRead[(int) $socket]; 
         unset($this->waitingForRead[(int) $socket]); 

         foreach ($tasks as $task) { 
             $this->schedule($task); 
         } 
     } 

     foreach ($wSocks as $socket) { 
         list(, $tasks) = $this->waitingForWrite[(int) $socket]; 
         unset($this->waitingForWrite[(int) $socket]); 

         foreach ($tasks as $task) { 
             $this->schedule($task); 
         } 
     } 
 }
 
stream_select 函数接受承载读取、写入以及待检查的socket的数组(我们无需考虑最后一类)。数组将按引用传递,函数只会保留那些状态改变了的数组元素。我们可以遍历这些数组,并重新安排与之相关的任务。

为了正常地执行上面的轮询动作,我们将在调度器里增加一个特殊的任务: 复制代码 代码如下:
 <?php 
 protected function ioPollTask() { 
     while (true) { 
         if ($this->taskQueue->isEmpty()) { 
             $this->ioPoll(null); 
         } else { 
             $this->ioPoll(0); 
         } 
         yield; 
     } 
 }
 

分享:PHP删除数组中特定元素的两种方法
这篇文章介绍了PHP中删除数组中特定元素的两种方法,有需要的朋友可以参考一下 方法一: 复制代码 代码如下: ?php $arr1 = array(1,3, 5,7,8); $key = array_search(3, $arr1); if ($key !== false) array_splice($arr1, $key, 1); var_dump($arr1); ? 输出: array(4)

来源:模板无忧//所属分类:PHP教程/更新时间:2013-07-03
相关PHP教程