内容简介:channel用于进程内跨协程通讯,按照角色分为生产协程和消费协程。生产协程,在channel已满时,会被挂起;消费协程,在channel为空是,也会被挂起。
前言
channel用于进程内跨协程通讯,按照角色分为生产协程和消费协程。
生产协程,在channel已满时,会被挂起;
消费协程,在channel为空是,也会被挂起。
看例子
<?php $chan = new \Swoole\Coroutine\Channel(50); function t4(\Swoole\Coroutine\Channel $chan) { Co::sleep(0.005); $chan->push([__METHOD__ => __LINE__]); } function t5(\Swoole\Coroutine\Channel $chan) { Co::sleep(0.005); $chan->push([__METHOD__ => __LINE__]); } go("t4", $chan); go("t5", $chan); go(function () use ($chan) { // chan元素个数 $chanNum = 1; while ($chanNum > 0) { $item = $chan->pop(); var_dump($item); $chanNum--; } });
分析
上面的例子,如果赋值$chanNum=1,会导致channel中有数据未被消费;
如果赋值$chanNum=3,由于channel数据不足,消费协程会挂起,程序无法正常退出。
准确设置channel元素个数,是很重要的事。
实践中,有些场景无法预测channel元素个数(例如请求第三方接口,如果有数据则push到channel,无数据则不push),那有什么解决办法嘛?
有!
保证生产者协程不挂起的前提下,在 php 的register_shutdown_function()函数中,去实现未完成的消费者功能
<?php register_shutdown_function(function() use ($chan) { go(function()use($chan){ $queue_num = $chan->stats()["queue_num"]; for($i=0;$i<$queue_num;$i++) { var_dump($chan->pop()); } }); });
这个办法能解决问题,但是显然不是那么优雅
消费者函数要重复写一遍,由于swoole协程的语法,无法复用这个问题,应该在swoole协程层面来处理,在register_shutdown_function()中处理,也只是临时解决办法
总结
swoole协程的push/pop机制,决定了需要设置一个合理的channel元素个数。
实践中某些场景,又无法准确评估这个值,只能用临时办法解决,希望swoole能提供更优雅的解决方式。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Swift Array 元素个数判断为0的方法哪种更好
- 用堆找出最小的 N 个数
- leetcode.69.求一个数的平方根
- 统计两个IP地址之间的IP个数
- 效率比较:几种方法判断一个数是否是素数
- C语言实现三个数从小到大排序/输出
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。