Created
July 29, 2021 06:31
-
-
Save xx10n31y/c947e03f935e75ad318c3dc8a05f35ef to your computer and use it in GitHub Desktop.
PHP PCNTL Alarm Simple Demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @references | |
* https://www.php.cn/php-weizijiaocheng-432036.html | |
* https://www.jianshu.com/p/139b0e43ef3f | |
* https://zhuanlan.zhihu.com/p/217622103 | |
* https://segmentfault.com/q/1010000000751497 | |
*/ | |
# 规定每执行一条低级语句就触发ticks信号 | |
declare(ticks=1); | |
# 实际应用产品调用类 | |
class ResolveTimeout | |
{ | |
public $flag = false; | |
# 相同功能方法1 | |
public function method1() | |
{ | |
echo 'method1' . PHP_EOL; | |
$rand = rand(1, 3); | |
echo 'method1_rand_sec:' . $rand . PHP_EOL; | |
sleep($rand); | |
echo 'method1_after_sleep' . PHP_EOL; | |
$this->finished(); | |
} | |
# 相同功能方法2 | |
public function method2() | |
{ | |
echo 'method2' . PHP_EOL; | |
$rand = rand(1, 4); | |
echo 'method2_rand_sec:' . $rand . PHP_EOL; | |
sleep($rand); | |
echo 'method2_after_sleep' . PHP_EOL; | |
$this->finished(); | |
} | |
# 相同功能方法3 | |
public function method3() | |
{ | |
echo 'method3' . PHP_EOL; | |
$rand = rand(3, 5); | |
echo 'method3_rand_sec:' . $rand . PHP_EOL; | |
sleep($rand); | |
echo 'method3_after_sleep' . PHP_EOL; | |
$this->finished(); | |
} | |
# 标识功能完全被调用 | |
private function finished() | |
{ | |
$this->flag = true; | |
} | |
} | |
# 注册触发ticks时被调用的函数 | |
// register_tick_function(function(){ | |
// echo 'asd'; | |
// },true); | |
$resolver = new ResolveTimeout(); | |
# 获取一个随机的可调用方法 | |
[$method, $rand] = getCallMethod(); | |
# 开始一个无限循环 直到flag为true(方法执行完毕) | |
while (true) { | |
try { | |
# 创建一个计时器, 在指定秒数后向进程发送一个SIGALRM信号 | |
pcntl_alarm(2); | |
# 监听SIGALRM信号, 使用匿名函数对超过计时器秒数作出处理 | |
pcntl_signal(SIGALRM, function () { | |
throw new Exception; | |
}); | |
# 实际方法调用 | |
$resolver->{$method}(); | |
# 清楚计时器 | |
pcntl_alarm(0); | |
} catch (Exception $exception) { | |
# 进入到catch模块, 代表上一个功能方法执行超时 | |
# 重新获取可执行功能方法 | |
[$method, $rand] = getCallMethod($rand); | |
echo "timeout" . PHP_EOL; | |
} | |
# 当flag为true时代表所调用的功能方法已完成操作且未超时 | |
# 跳出无限循环 | |
if ($resolver->flag === true) { | |
break; | |
} | |
} | |
# 返回一个非previous使用的方法 | |
function getCallMethod($previous=9999) | |
{ | |
$methods = [ | |
'method1', | |
'method2', | |
'method3' | |
]; | |
$rand = rand(0, count($methods)-1); | |
if ($rand == $previous) { | |
getCallMethod($previous); | |
} | |
return [$methods[$rand], $rand]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment