echo "test-1\n"; go(function(){ Co::sleep(2); // 協程讓出控制,進入協程控制隊列。繼續往下執行 echo "coroutine 111 \n"; }); echo "test-2"; go(function(){ echo "coroutine 222 \n"; }); echo "test-3\n";
執行過程:php
一、運行php Demo.php 系統啓動一個新進程
二、執行到go()函數,在當前進程中生成一個協程
三、協程中遇到IO阻塞(Co::sleep(2)),協程讓出控制, 進入協程調度隊列
四、進程繼續向下執行,輸出:test-2
五、執行下一個協程, 輸出:coroutine 222
六、以前的協程準備就緒, 繼續執行, 輸出:coroutine 111mysql
結果:經過以上代碼例子,能夠了解到協程和進程的關係,協程的調度sql
計算機任務分爲2種數據庫
一、CPU密集型: 好比加減乘除等科學計算
二、IO 密集型: 好比網絡請求, 文件讀寫等數組
併發swoole
因爲CPU切換任務很是快, 快到人類能夠感知的極限, 就會有不少任務同時執行的錯覺網絡
並行併發
同一個時刻, 同一個CPU只能執行同一個任務, 要同時執行多個任務, 就須要有多個CPU才行函數
協程適合的是 IO 密集型應用, 由於協程在 IO阻塞時會自動調度, 減小IO阻塞致使的時間損失高併發
普通程序運行以下:
$n = 3; for($i=0; $i < $n; $i++){ sleep(1); echo microtime(true) . " : hello {$i}".PHP_EOL; } echo "hello main".PHP_EOL;
多協程運行以下:
$n = 3; for ($i = 0; $i < $n; $i++) { go(function () use ($i) { Co::sleep(1); echo microtime(true) . ": hello {$i}".PHP_EOL; }); }; echo "hello main".PHP_EOL;
結果
一、普通的程序運行時遇到 IO阻塞 會致使的性能損失
二、多協程,遇到IO阻塞時發生調度, IO就緒時恢復運行
說明
一、sleep() 能夠看作是 CPU密集型任務, 不會引發協程的調度
二、Co::sleep() 模擬的是 IO密集型任務, 會引起協程的調度
消費協程:在channel爲空是,也會被掛起。
$chan = new Chan(); go(function()use($chan){ for($i=0;$i<5;$i++){ $chan->push($i); echo "順序插入{$i}".PHP_EOL; } }); echo "順序執行".PHP_EOL; go(function()use($chan){ while(!$chan->isEmpty()){ $res = $chan->pop(); echo "順序消費{$res}".PHP_EOL; } });
結果能夠看出生產者協程和消費者協程是交替運行的,而協程切換的時機則是在運行到 push 和 pop 的時候,首先會進入生產者協程,而後生產了一條數據,而後代碼繼續執行輸出「順序執行」的字符串並建立了消費者協程;因爲前面已經 push 了一條數據因此此時的 $channel->isEmpty() 是非空狀態,再執行 pop。
<?php class Mysql { public $pool; public $config = [ 'maxnum' => 20, // 最大鏈接數 'mysql' => [ // 數據庫配置 'host'=>'192.168.1.13', 'port'=>3306, 'user'=>'root', 'password'=>'123456', 'database'=>'test' ] ]; /** 初始化 */ public function __construct() { $maxnum = $this->config['maxnum']; $this->pool = new \Swoole\Coroutine\Channel($maxnum); for($i=1; $i<$maxnum; $i++){ $mysqlConnect = $this->createConnect(); $this->push($mysqlConnect); } } /** 建立數據庫鏈接 */ public function createConnect() { $mysql = new \Swoole\Coroutine\MySQL(); // 使用鏈接mysql組件 $mysql->connect($this->config['mysql']); // 鏈接操做 return $mysql; } /** 生產者插入 */ public function push($source){ return $this->pool->push($source); } /** 銷燬 */ public function pop(){ return $this->pool->pop(); } /** 當前鏈接數 */ public function length(){ return $this->pool->length(); } } // 建立一個協程 go(function(){ $model = new Mysql(); $conn = $model->pop(); // 獲取鏈接 $res = $conn->query('show tables'); // 查詢當前庫的有哪些表 // 逐條打印表名 foreach($res as $key => $val){ echo $val['Tables_in_test'].PHP_EOL; } });