协程
协程可以简单理解为线程,只不过这个线程是用户态的,不需要操作系统参与,创建销毁和切换的成本非常低,和线程不同的是协程没法利用多核 cpu 的,想利用多核 cpu 需要依赖 Swoole
的多进程模型。—— swoole 协程一章
我的理解
可以把协程看成一道小学数学的一道题目:“合理安排时间”,来我们先做一道题目:
小明下班后回家煮饭,煲汤需要 10 分钟,煮饭需要 8 分钟, 炒菜需要 5 分钟,,请问小明最少需要多少分钟能煮好饭?
下面用 sleep()
模拟 IO 操作
同步版煮饭
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| <?php
class SyncCook { public function cook() { $startTime = time();
echo "开始煲汤..." . PHP_EOL; sleep(10); echo "汤好了..." . PHP_EOL;
echo "开始煮饭..." . PHP_EOL; sleep(8); echo "饭熟了..." . PHP_EOL;
echo "放油..." . PHP_EOL; sleep(1); echo "煎鱼..." . PHP_EOL; sleep(3); echo "放盐..." . PHP_EOL; sleep(1); echo "出锅..." . PHP_EOL;
var_dump('总耗时:' . (time() - $startTime) . ' 分钟');die; } }
$sync = new SyncCook(); $sync->cook();
|
总耗时:23 分钟
代码很容易看懂,等待汤煮好之后再煮饭,然后再等待饭煮好再炒菜,生活中不会这样操作吧?这就要引入协程来解决这个问题了。
协程版煮饭
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
| <?php
use Swoole\Coroutine; use Swoole\Coroutine\WaitGroup;
class SwooleCook { public function cook() { $startTime = time();
Swoole\Runtime::enableCoroutine($flags = SWOOLE_HOOK_ALL);
Co\run(function () { $wg = new WaitGroup(); $result = [];
$wg->add(); Coroutine::create(function () use ($wg, &$result) { echo "开始煲汤..." . PHP_EOL; sleep(8); echo "汤好了..." . PHP_EOL;
$result['soup'] = '一锅汤'; $wg->done(); });
$wg->add(); Coroutine::create(function () use ($wg, &$result) { echo "开始煮饭..." . PHP_EOL; sleep(10); echo "饭熟了..." . PHP_EOL;
$result['rice'] = '一锅米饭'; $wg->done(); });
$wg->add(); Coroutine::create(function () use ($wg, &$result) { // 煎鱼的过程必须放在一个协程里面执行,如果不是的话可能鱼还没煎好就出锅了 // 因为开启协程后,IO全是异步了,在此demo中每次遇到sleep都会挂起当前协程 // 切换到下一个协程执行。 // 例如把出锅这一步开启一个新协程执行,则在煎鱼的时候鱼,鱼就出锅了。 echo "放油..." . PHP_EOL; sleep(1); echo "煎鱼..." . PHP_EOL; sleep(3); echo "放盐..." . PHP_EOL; sleep(1); echo "出锅..." . PHP_EOL;
$result['food'] = '鱼香肉丝'; $wg->done(); });
$wg->wait();
var_dump($result); });
var_dump('总耗时:' . (time() - $startTime) . ' 分钟'); } }
$swoole = new SwooleCook(); $swoole->cook();
|
总耗时:10 分钟
答:小明最少需要 10 分钟能煮好饭。