这篇文章给大家分享的是有关php如何使用多进程的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
代码:
<?php class process{ public $num = 10; # 进程数 public $timeout = 4; # 延迟时间 public $pipedir = "pipe/"; # 管道目录 public $logdir = "log/"; # 日志目录 public $errlog = "err.log"; # 错误日志 public $successlog = "success.log"; # 成功日志 public function __construct(){ $pipedir = $this->pipedir; $logdir = $this->logdir; if(!is_dir($pipedir)){ if(!mkdir($pipedir)){ $this->write_log(1,"创建管道目录{$pipedir}失败"); } } if(!is_dir($logdir)){ if(!mkdir($logdir)){ $this->write_log(1,"创建日志目录{$logdir}失败"); } } if (!function_exists('pcntl_fork')) { $this->write_log(1,'未安装pcntl扩展'); exit; } } private function write_log($type,$msg){ $logdir = $this->logdir; $errlog = $this->errlog; $successlog = $this->successlog; $prelog = date('Y-m-d H:i:s').":"; if($type == 1){ $logname = $logdir.$errlog; }else{ $logname = $logdir.$successlog; } file_put_contents($logname,$prelog.$msg.PHP_EOL,FILE_APPEND); } public function run($name){ $num = $this->num; $timeout = $this->timeout; $pipedir = $this->pipedir; $pipefile = $pipedir.posix_getpid(); if (!posix_mkfifo($pipefile, 0666)) { $this->write_log(1,"创建管道文件{$pipefile}失败"); exit; } # 处理任务 for ($i = 0; $i < $num; ++$i ) { $cpid = pcntl_fork(); # 创建子进程 if ($cpid == 0) { # 子进程过程 call_user_func($name,$i); $pw = fopen($pipefile, 'w'); fwrite($pw, $i."\n"); # 当前任务处理完比,在管道中写入数据 fclose($pw); exit(0); # 执行完后退出 } } # 父进程 $pr = fopen($pipefile, 'r'); stream_set_blocking($pr, FALSE); # 将管道设置为非堵塞,用于适应超时机制 $pdata = ''; # 存放管道中的数据 $sline = 0; # 成功执行的进程数量 $stime = time(); while ($sline < $num && (time() - $stime) < $timeout) { $tline = fread($pr, 1024); if (empty($tline)) { continue; } # 用于分析多少任务处理完毕,通过'\n'标识 foreach(str_split($tline) as $v) { if ("\n" == $v) { ++$sline; } } $pdata .= $tline; } $this->write_log(2,"总共{$sline}个任务执行成功"); fclose($pr); unlink($pipefile); # 删除管道,已经没有作用了 # 等待子进程执行完毕,避免僵尸进程 $n = 0; while ($n < $num) { $status = -1; $cpid = pcntl_wait($status, WNOHANG); if ($cpid > 0) { $this->write_log(2,"进程{$cpid}执行结束"); ++$n; } } # 验证结果,主要查看结果中是否每个任务都完成了 $arr = array(); foreach(explode("\n", $pdata) as $i) { if (is_numeric(trim($i))) { array_push($arr, $i); } } $arr = array_unique($arr); if ( count($arr) == $num) { $this->write_log(2,var_export($arr,true)); } else { $this->write_log(1,"执行成功数量:".count($arr)); $this->write_log(1,"执行成功的线程:".var_export($arr,true)); } } }
测试:
$process = new process(); $process->num = 5; # 修改进程数为5 $process->run('todo'); function todo($pid){ $num = 19; # 总任务数 $anum = ceil($num/5); # 平均每个进程处理任务数 $lnum = $num - $anum*(5-1); # 最后一个进程处理任务数 $minnum = $anum*$pid; # 当前进程处理的最小值 $maxnum; # 当前进程处理的最大值 if($pid<(5-1)){ $maxnum = $minnum + $anum; }else{ $maxnum = $num; } for($i=$minnum;$i<$maxnum;$i++){ echo "进程号:{$pid};输出:{$i}".PHP_EOL; } }
输出:
进程号:1;输出:4 进程号:1;输出:5 进程号:1;输出:6 进程号:1;输出:7 进程号:2;输出:8 进程号:2;输出:9 进程号:2;输出:10 进程号:2;输出:11 进程号:3;输出:12 进程号:3;输出:13 进程号:3;输出:14 进程号:3;输出:15 进程号:4;输出:16 进程号:4;输出:17 进程号:4;输出:18 进程号:0;输出:0 进程号:0;输出:1 进程号:0;输出:2 进程号:0;输出:3
感谢各位的阅读!关于“php如何使用多进程”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!