于server其中编程。为了实现异步。通常情况下,需要回调。比例如下面的代码

function send($value) {
$data = process($value);
onReceive($data);
} function onReceive($recv_value) {
var_dump($recv_value);
} function process($value) {
return $value+1;
} $send_value = 1;
send($send_value);


实现的东西非常easy,事实上就是将send_value发送到远端,远端server对其进行加一操作后,发送回来,于是在onReceive中我们能够得到远端server的返回值recv_value。

可是这种代码就会看上去比較支离破碎,尤其是在process其中再次进行远程过程调用的时候。会变得更加难以开发和维护。协程就是为了解决这种问题,使得异步的代码看起来同步化。

以下就是使用php的yield完毕代码调度的演示样例(假设想看懂这段代码。须要首先了解一下php 5.5的新特性generator和yield)

框架代码例如以下:

class CCoroutine {

    /**
*
* @var Generator
*/
public $coroutine; /**
*
* @var miexed null or CCoroutine
*/
public $father; public function __construct($coroutine, $father = null) {
$this->coroutine = $coroutine;
$this->father = $father;
} } class AsyncTask { public $data; public function __construct($data) {
$this->data = $data;
} } abstract class CoroutineScheduler { protected $coroutine = NULL; abstract function send_and_receive($value); public function run($data) {
$co = $this->send_and_receive($data);
$ccoroutine = new CCoroutine($co);
$this->schedule($ccoroutine);
} protected function schedule($ccoroutine) {
$task = $ccoroutine->coroutine->current();
//假设当前值为空,表示这个$ccoroutine应该已经结束了
if (is_null($task)) {
if (is_null($ccoroutine->father)) {
//已经彻底调度结束了--通常是onRecieve方法执行到最后一步了
return;
} else {
//注意,假设执行到这个分支,则表示子生成器没有给父生成器传数据
//子生成器可能是通过引用传递来改变父生成器的变量值
//所以这个时候仅仅要调度父生成器就能够了
$ccoroutine->father->coroutine->next();
$father = $ccoroutine->father;
$this->schedule($father);
unset($ccoroutine);
}
} else {
if (is_object($task) && $task instanceof AsyncTask) {
//当task是异步数据请求的时候,開始处理socket而且将进程熄火在这里
$this->dealTask($task, $ccoroutine);
} elseif (is_object($task) && $task instanceof \Generator) {
//当task是生成器时,表示当前生成器又有了子生成器的调用
$newcc = new CCoroutine($task, $ccoroutine);
$this->schedule($newcc);
} elseif ($ccoroutine->father != null) {
//注意,假设执行到这个分支,则表示在子的生成器里调用了yield $str;这种写法
//我们规定这种写法是在给父生成器传数据,所以当前生成器就会终止调用了转而去调度父生成器
$ccoroutine->father->coroutine->send($task);
$father = $ccoroutine->father;
$this->schedule($father);
unset($ccoroutine);
}
}
} protected function dealTask($task, $ccoroutine) {
$this->coroutine = $ccoroutine;
$this->send($task->data);
} public function send($value) {
$data = $this->process($value);
$this->onReceive($data);
} public function process($value) {
return $value+1;
} protected function onReceive($data) {
$this->coroutine->coroutine->send($data);
$this->schedule($this->coroutine);
} }

框架将 send, onReceive等函数所有都封装好了,使得调用方的代码看起来能够是同步的代码

调用方代码例如以下:

//1. 须要去实现CoroutineScheduler的send_and_receive函数,主要是为了在里面拿到返回值
class Solution extends CoroutineScheduler { public function send_and_receive($data) {
$result = (yield new AsyncTask($data));
var_dump($result); } } //2. 在最外层去调用框架的代码。给出输入參数 $data
$s = new Solution();
$data = 1;
$s->run($data);

版权声明:本文博客原创文章,博客,未经同意,不得转载。

PHP实现协同程序的更多相关文章

  1. Lua 学习笔记(九)协同程序(线程thread)

    协同程序与线程thread差不多,也就是一条执行序列,拥有自己独立的栈.局部变量和命令指针,同时又与其他协同程序共享全局变量和其他大部分东西.从概念上讲线程与协同程序的主要区别在于,一个具有多个线程的 ...

  2. Unity3D协同程序(Coroutine)

    摘要下: 1. coroutine, 中文翻译"协程".这个概念可能有点冷门,不过百度之,说是一种很古老的编程模型了,以前的操作系统里进程调度里用到过,现在操作系统的进程调度都是根 ...

  3. 【转】Unity中的协同程序-使用Promise进行封装(三)

    原文:http://gad.qq.com/program/translateview/7170967 译者:崔国军(飞扬971)    审校:王磊(未来的未来) 在这个系列的最后一部分文章,我们要通过 ...

  4. 【转】Unity中的协同程序-使用Promise进行封装(二)

    原文:http://gad.qq.com/program/translateview/7170970 译者:王磊(未来的未来)    审校:崔国军(飞扬971)   在上一篇文章中,我们的注意力主要是 ...

  5. 【转】Unity中的协同程序-使用Promise进行封装(一)

    原文:http://gad.qq.com/program/translateview/7170767 译者:陈敬凤(nunu)    审校:王磊(未来的未来) 每个Unity的开发者应该都对协同程序非 ...

  6. 【转】关于Unity协同程序(Coroutine)的全面解析

    http://www.unity.5helpyou.com/2658.html 本篇文章我们学习下unity3d中协程Coroutine的的原理及使用 1.什么是协调程序 unity协程是一个能暂停执 ...

  7. Lua中的协同程序 coroutine

    Lua中的协程和多线程很相似,每一个协程有自己的堆栈,自己的局部变量,可以通过yield-resume实现在协程间的切换.不同之处是:Lua协程是非抢占式的多线程,必须手动在不同的协程间切换,且同一时 ...

  8. Unity 中的协同程序

    今天咱就说说,协同程序coroutine.(这文章是在网吧敲的,没有unity,但是所有结论都被跑过,不管你信得过我还是信不过我,都要自己跑一下看看,同时欢迎纠错)先说说啥是协程:协同程序是一个非常让 ...

  9. 9. MonoBehaviour.StartCoroutine 开始协同程序

    function StartCoroutine (routine : IEnumerator) : Coroutine 描述:开始协同程序. 一个协同程序在执行过程中,可以在任意位置使用yield语句 ...

  10. 【笨木头Lua专栏】基础补充08:协同程序之resume-yield间的数据返回

    这次要介绍几个事实上非常easy,可是一定要小心的返回值规则. 笨木头花心贡献,哈?花心?不,是用心~ 转载请注明.原文地址: http://www.benmutou.com/archives/173 ...

随机推荐

  1. 用XAML做网页!!—开篇

    原文:用XAML做网页!!-开篇 这几日一直没发表新文章,一来是因为事比较多,二来就是我在研究使用XAML挑战传统HTML来做网页,这很可能是在全球的首次尝试,至少我从未找到任何可供参考的相关资料. ...

  2. varchar 分享影响记忆 试

    准备数据 sysbench --test=oltp --oltp-nontrx-mode=update_key --mysql-table-engine=innodb --oltp-table-siz ...

  3. 初识缓存以及ehcache初体验

    1.缓存的意义 缓存机制就是将数据库中经常使用的数据取出放入内存中.程序调用时直接从内存中取,丌用每次使用  数据都訪问数据库,这样提高了效率. 2.缓存须要关注的问题 1)  缓存的更新 缓存中的数 ...

  4. 理解RESTful架构(转)

    越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high latency).高 ...

  5. PHP+Mysql————表单数据插入数据库及数据提取

    站点在进行新用户注冊时,都会将用户的注冊信息存入数据库中,须要的时候再进行提取.今天写了一个简单的实例. 主要完毕下面几点功能: (1)用户进行注冊,实现password反复确认,验证码校对功能. ( ...

  6. CentOS tripwire-文件指纹

    Tripwire是目前最为著名的unix下文件系统完整性检查的软件工具,这一软件采用的技术核心就是对每个要监控的文件产生一个数字签名,保留下来.当文件现在的数字签名与保留的数字签名不一致时,那么现在这 ...

  7. HDU 1856 More is better(并查集+离散化)

    题目地址:HDU 1856 水题.因为标号范围太大,而数据数仅仅有10w,所以要先进行离散化.然后就是裸的并查集了. 代码例如以下: #include <iostream> #includ ...

  8. 【原创】java中的父进程子进程 —— 坑爹的java Runtime.getRuntime().exec

    最近有一个需求,需要用一个java进程启动多个子进程来完成并发任务.由于必须给用户完成任务的反馈,所以需要父进程记录子进程的生命周期. exec方法返回一个Process对象,在当前进程内调用该对象的 ...

  9. lua学习笔记11:lua中的小技巧

    lua中的小技巧,即基础lua语言本身的特种,进行一个些简化的操作 一. 巧用or x = x or v 等价于: if not x then x = v end 假设x为nil或false,就给他赋 ...

  10. 使用Intellij Idea生成可执行文件jar,开关exe文件步骤

    确保其Java代码是没有问题的,在IDEA常执行的,然后.按以下步骤: 步骤一:打开File -> Project Structure -> Artifacts,例如以下图 步骤二:点击& ...