協程是一種輕量級的線程,由用戶代碼來調度和管理,而不是由操作系統內核來進行調度,也就是在用戶態進行
創建協程方法
co函數
public function test(){
echo "first id: ". Coroutine::id().PHP_EOL;
co(function () {
echo "second id: ". Coroutine::id().PHP_EOL;
echo "這是co方法產生的協程".PHP_EOL;
});
}
訪問/index/test
http://ip:9501/index/test
終端顯示結果
first id: 2
second id: 3
這是co方法產生的協程
go函數
public function test(){
echo "first id: ". Coroutine::id().PHP_EOL;
go(function () {
echo "second id: ". Coroutine::id().PHP_EOL;
echo "這是go方法產生的協程".PHP_EOL;
});
}
訪問/index/test
http://ip:9501/index/test
終端顯示結果
first id: 2
second id: 3
這是go方法產生的協程
Coroutine::create方法
use Hyperf\Utils\Coroutine;
public function test(){
echo "first id: ". Coroutine::id().PHP_EOL;
Coroutine::create(function(){
echo "second id: ". Coroutine::id().PHP_EOL;
echo "這是coroutine::create方法產生的協程".PHP_EOL;
});
}
訪問/index/test
http://ip:9501/index/test
終端顯示結果
first id: 2
second id: 3
這是coroutine::create方法產生的協程
協程相關方法
判斷當前是否處於協程環境(Hyperf\Utils\Coroutine::inCoroutine(): bool)
Hyperf\Utils\Coroutine::inCoroutine(): bool
獲取當前協程id
Hyperf\Utils\Coroutine::id()
channel通道
Channel 主要用於協程間通訊
public function test(){
co(function () {
$channel = new \Swoole\Coroutine\Channel();
co(function () use ($channel) {
$channel->push('子協程的數據');
});
$data = $channel->pop();
echo "獲取子協程數據: ".$data;
});
}
訪問/index/test
http://ip:9501/index/test
獲取子協程數據: 子協程的數據
defer特性
public function test(){
Coroutine::defer(function(){
echo "第一個defer".PHP_EOL;
});
Coroutine::defer(function(){
echo "第二個defer".PHP_EOL;
});
Coroutine::defer(function(){
echo "第三個defer".PHP_EOL;
});
echo 'defer test'.PHP_EOL;
}
訪問/index/test
http://ip:9501/index/test
終端結果顯示
defer test
第三個defer
第二個defer
第一個defer
WaitGroup特性
public function test(){
$wg = new \Hyperf\Utils\WaitGroup();
// 計數器加二
$wg->add(2);
// 創建協程 A
co(function () use ($wg) {
mt_srand();
$time = mt_rand(1, 5);
sleep($time);
// some code
echo "協程A執行完成".PHP_EOL;
//計算器減一
$wg->done();
});
// 創建協程 B
co(function () use ($wg) {
mt_srand();
$time = mt_rand(1, 5);
sleep($time);
// some code
echo "協程B執行完成".PHP_EOL;
// 計數器減一
$wg->done();
});
// 等待協程 A 和協程 B 運行完成
$wg->wait();
echo "全部程序執行完成".PHP_EOL;
}
訪問/index/test
http://ip:9501/index/test
終端結果顯示
協程B執行完成
協程A執行完成
全部程序執行完成
Parallel特性
use Hyperf\Utils\Exception\ParallelExecutionException;
use Hyperf\Utils\Coroutine;
use Hyperf\Utils\Parallel;
public function test(){
$parallel = new Parallel();
$parallel->add(function () {
mt_srand();
$time = mt_rand(1, 5);
sleep($time);
echo "協程A執行完成".PHP_EOL;
return Coroutine::id();
});
$parallel->add(function () {
mt_srand();
$time = mt_rand(1, 5);
sleep($time);
echo "協程B執行完成".PHP_EOL;
return Coroutine::id();
});
try{
// $results 結果為 [1, 2]
$results = $parallel->wait();
echo "results:".PHP_EOL;
var_dump($results);
} catch(ParallelExecutionException $e){
// $e->getResults() 獲取協程中的返回值。
// $e->getThrowables() 獲取協程中出現的異常。
var_dump($e->getResults());
}
}
訪問/index/test
http://ip:9501/index/test
終端結果顯示
協程B執行完成
協程A執行完成
results:
array(2) {
[1]=>
int(4)
[0]=>
int(3)
}
簡寫版
$results = parallel([
function () {
mt_srand();
$time = mt_rand(1, 5);
sleep($time);
echo "協程A執行完成".PHP_EOL;
return Coroutine::id();
},
function () {
mt_srand();
$time = mt_rand(1, 5);
sleep($time);
echo "協程B執行完成".PHP_EOL;
return Coroutine::id();
}
]);
協程上下文
public function test(){
co(function(){
Context::set('name','huyongjian');
$name = Context::get('name');
echo $name.PHP_EOL;
});
}
訪問/index/test
http://ip:9501/index/test
終端結果顯示
huyongjian