协程是一种轻量级的线程,由用户代码来调度和管理,而不是由操作系统内核来进行调度,也就是在用户态进行
创建协程方法
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