以上解析可以参考PHP官方文档。
...
以及这篇详细文档:
我就以他实现的协程多任务调度为基础做一下例子说明并说一下关于我在阻塞方面所做的一些思考。
自定义简单定时执行任务示例:
(此例子必须依赖于以上鸟哥实现的协程调度代码)
start = time();
$this->timer = $timer;
$this->callback = $callback;
}
public function run() {
if($this->valid()) {
$callback = $this->callback;
$callback($this->value ++,$this);
$this->start = time();
}
}
/**
* 定时执行检查
*/
public function valid() {
$end = time();
if($end - $this->start >= $this->timer) {
return true;
} else {
return false;
}
}
public function setEnd($isEnd) {
$this->isEnd = $isEnd;
}
public function getEnd() {
return $this->isEnd;
}
}
/**
- 模拟阻塞的协程1
-
*/
function taskObject1() {
$timer = new timer(1,function($value,timer $timer) {
if($value >= 5) {
$timer->setEnd(true);
}
echo '
'.'A '.$value;
});
$tid = (yield getTaskId());
while (true) {
if($timer->getEnd() == true) {
break;
}
yield $timer->run();
}
}
/**
- 模拟阻塞的协程2
-
*/
function taskObject2() {
$timer = new timer(2,timer $timer) {
if($value >= 3) {
$timer->setEnd(true);
}
echo '
'.'B '.$value;
});
$tid = (yield getTaskId());
while (true) {
if($timer->getEnd() == true) {
break;
}
yield $timer->run();
}
}
$scheduler = new Scheduler;
$scheduler->newTask(taskObject1());
$scheduler->newTask(taskObject2());
$scheduler->run();
以上实现的是:
- 产生两个任务,并行执行,并且给每个任务在执行的时候模拟几秒钟的阻塞;
- 让协程切换的时候能顺利切换,其中的任务阻塞不相互影响;
思考:
我为什么要做以上这件事情呢?因为我发现协程实现虽然很强大也很有意思,能让多任务并行,但是我在其中一个任务里调用系统函数 sleep()
的时候,阻塞任务会阻止协程切换,其实从协程的实现原理上来书也是这么回事。
那么,我也就想模拟协程阻塞,但是不产生阻塞看是否可行。PHP本身只提供了生成器为协程调用提供了支撑,如果不依赖扩展,没有提供多线程的程序实现方式,没有java那么强大,可以开子线程进行实现。
我印象中java的子线程是独立执行且不会相互阻塞的,所以我在想,PHP既然可以实现类似于多线程这样的机制,那么能不能实现调用过程中非阻塞呢?
经过这样一个实现和思考,一开始是陷入了一个误区的,是由于PHP原生函数 sleep()
阻塞造成的思维误区,那就是认为要想真正实现非阻塞或者说实现异步的话,是必须依赖于语言底层的。
后来,我想明白了一个道理,既然某个方法或者函数在执行过程中,会产生阻塞,那么把当前这个方法换成自定义的,做成非阻塞(相对于整个协程调度来说)不就行了吗?比如上面的定时执行我自己实现了一个。
而另一方面,协程调度本身的目的也是为了把任务执行过程切成尽量小片,从而快速切换执行,达到并行的目的。从这方面来看,协程应该也算是一种程序设计思想。
以下是一个程序切成尽量小片执行的例子:
foreach (xrange(1,1000000) as $num) {
echo $num,"\n";
}
这个例子是把原本用 range 生成一个很大的整型数组的方式切换为分片执行,也就是说在遍历的时候再去取到指定的值,从代码上来看,内存消耗相对于之前来说就非常小了。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对编程之家的支持。
(编辑:ASP站长网)