這篇文章主要給大家介紹了關於PHP中協程和阻塞的一些理解與思考,文中透過範例程式碼介紹的非常詳細,對大家學習或使用PHP具有一定的參考學習價值,需要的朋友們下面跟著小編來一起學習學習吧。
前言
本文主要介紹了PHP中協程與阻塞的理解與思考,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹:
進程、執行緒、協程
PHP中的協程實作基礎yield
yield的根本實作是生成器類,而迭代器類別是迭代器介面的實作:
Generator implements Iterator { public mixed current ( void ) // 返回当前产生的值 public mixed key ( void ) // 返回当前产生的键 public void next ( void ) // 生成器继续执行 public void rewind ( void ) // 重置迭代器,如果迭代已经开始了,这里会抛出一个异常。 // renwind的执行将会导致第一个yield被执行, 并且忽略了他的返回值. public mixed send ( mixed $value ) // 向生成器中传入一个值,并且当做 yield 表达式的结果,然后继续执行生成器。如果当这个方法被调用时,生成器 // 不在 yield 表达式,那么在传入值之前,它会先运行到第一个 yield 表达式。 public void throw ( Exception $exception ) // 向生成器中抛入一个异常 public bool valid ( void ) // 检查迭代器是否被关闭 public void __wakeup ( void ) // 序列化回调,抛出一个异常以表示生成器不能被序列化。 }
自訂簡單定時執行任務範例:
class timer { private $start = 0; // 定时开始时间 private $timer; // 间隔的时间差,单位秒 private $value = 0; // 产生的结果值 private $callback; // 异步回调 private $isEnd = false; // 当前定时器任务是否结束 public function __construct($timer,callable $callback) { $this->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 '<br>'.'A '.$value; }); $tid = (yield getTaskId()); while (true) { if($timer->getEnd() == true) { break; } yield $timer->run(); } } /** * 模拟阻塞的协程2 * */ function taskObject2() { $timer = new timer(2,function($value,timer $timer) { if($value >= 3) { $timer->setEnd(true); } echo '<br>'.'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() 的時候,阻塞任務會阻止協程切換,其實從協程的實現原理上來書也是這麼回事。
sleep() 阻塞造成的思維誤區,那就是認為要想真正實現非阻塞或說實現非同步的話,是必須依賴語言底層的。
以下是一個程式切成盡量小片執行的例子:
#
// 一个简单的例子 <?php function xrange($start, $end, $step = 1) { for ($i = $start; $i <= $end; $i += $step) { yield $i; } } foreach (xrange(1, 1000000) as $num) { echo $num, "\n"; }
總結#
以上是php中關於協程與阻塞的深入理解的詳細內容。更多資訊請關注PHP中文網其他相關文章!