LMLPHP后院

谈谈 PHP 协程的任务调度技术

maybe yes 发表于 2017-08-09 08:34

其实 PHP 的 yield 是做死的节奏。因为像我之前一篇文章提到的 PHP 的 ArrayAccess 一样,不懂或不知道它并不会影响一个程序员的开发与设计。

也许他们实现 yield,只是为了实现而实现,其他语言有的东西 PHP 当然得有,就这么一个理由比较有说服力。

关于 yield 在 PHP 程序里面的作用和好处是什么?我个人能想到的就是,比如一个傻逼写了一堆脚本,如果要维护这堆脚本怎么办,于是他们想到了一个好的办法,把每个脚本的代码用 function 包裹起来,在循环里面加上 yield,然后写一个最简单的任务调度管理。于是这样看似就搞定了这些恶劣的代码,几乎不用做什么修改,这样其实是很偷懒的做法,他们借助了语言级别的能力来管理这些垃圾代码,只会使得垃圾代码越来越难维护。

帮助理解 yield 的测试代码:

$ php -r 'yield;';
PHP Fatal error:  The "yield" expression can only be used inside a function in Command line code on line 1

[ 2017-08-09T00:05:13+08:00 ] /, LMLPHP Fatal Error:The "yield" expression can only be used inside a function in line 6

可以看出,yield 只能包裹在 function 中。yield 不同于线程和进程,它是编译器实现的执行控制,而后者是操作系统层面的时间片控制。说的更直白一点,yield 就是高级的 goto 语句,并且还可以进行简单的双向通信。

看如下最简单的任务调度控制:

$coroutineArr = array();
require DEFAULT_THEME_PATH.'index/script/task_1.php';
require DEFAULT_THEME_PATH.'index/script/task_2.php';

$coroutineArr[] = task_1();
$coroutineArr[] = task_2();

$firstTime = true;
for(;;){
        foreach ($coroutineArr as $k => $v) {
                if ($firstTime) {
                        $v->current();
                } else {
                        $v->next();
                }
        }
        $firstTime = false;
}

yield 中断返回 generator 对象,该对象一迭代默认会执行 rewind 方法,所以加上了第一次的判断,以免第一次没有执行。另外的 send 方法效果其实和 next 一样,唯一的不同就是可以发送数据。

yield 的作用其实只是中断,类似于 goto 语句,这样的代码导致阅读理解起来非常费力,而任务调度是我唯一能想到的 yield 的作用,方便管理垃圾代码。其实仔细一想,yield 能做的所有的事情,不使用 yield 照样可以相同效果的完成。学面向对象是为什么,支持面向对象是为什么,就是为了方便管理复杂的代码控制流程。像上面的任务调度,使用观察者模式一样可以同等效果的完成,也许稍微麻烦一点点,但性能应该比 yield 要好。

相关文章
LMLPHP,可爱滴WEB开发框架

2017-09-24 00:21:46 1506183706 0.005404