Closure 任务管理,可以控制Closure超时时间 closureCollection = $closureCollection; $this-timeout = $timeout; } /** * 运行子进程 * * @param bool $isTimeout 任务是否会超时 * @throws \Exception */ public function run($i
closureCollection = $closureCollection;
$this->timeout = $timeout;
}
/**
* 运行子进程
*
* @param bool $isTimeout 任务是否会超时
* @throws \Exception
*/
public function run($isTimeout = false)
{
// 检查
if (!$this->_checkRun()) {
return true;
}
// 创建子进程执行任务
foreach ($this->closureCollection as $clousre) {
$pid = pcntl_fork();
if ($pid === 0) {
// 子进程执行
$clousre();
// 一定要终止子进程
exit(0);
} else if ($pid > 0) {
$tmp['pid'] = $pid;
$tmp['startTime'] = microtime(true);
$this->pidCollection [] = $tmp;
} else {
throw new \Exception("创建子进程失败");
}
// 停止0.2s创建
usleep(200 * 1000);
}
// 是否需要管理超时进程
if ($isTimeout) {
$this->_killTimeoutPids();
}
}
/**
* 检查是否可以run
*
* @return bool
*/
private function _checkRun()
{
// closure集合为空不能run
if (empty($this->closureCollection)) {
return false;
}
return true;
}
/**
* 杀死超时进程
*/
private function _killTimeoutPids()
{
// 终止超时的子进程
while (true) {
foreach ($this->pidCollection as $key => $pidArr) {
// 如果超过超时时间,则终止
if (microtime(true) - $pidArr['startTime'] > $this->timeout) {
posix_kill($pidArr['pid'], 9);
unset($this->pidCollection[$key]);
}
}
// 终止
if (empty($this->pidCollection)) {
break;
}
// 1s检查一次
sleep(1);
}
}
}
