需求
对指定数量的多个任务并发执行,并控制进程数
进程&线程:
进程间相互独立,不影响。
代码示例:
<?php
$task = 0; //任务id
$taskNum = 10; //任务总数
$processNumLimit = 2; //子进程总量限制
while(true){
//产生分支
$processid = pcntl_fork();
//创建子进程失败
if( $processid == -1 ){
echo "create process error!\n";
exit(1);
}
//主进程,获得子进程pid
elseif($processid){
$task++; //下一个任务
$currentProcessid = posix_getpid(); //当前进程的Id
$parentProcessid = posix_getppid(); // 父级进程的ID
$phpProcessid = getmypid(); //当前php进程的id
echo "task:",$task,"\tprocessid:",$processid,"\tcurrentProcessid:",$currentProcessid,"\tparentProcessid:",$parentProcessid,"\tphpProcessid:",$phpProcessid,"\n";
//控制进程数
if($task >= $processNumLimit) {
echo "wait chl start!\n";
$exitid = pcntl_wait($status); //等待退出
echo "wait chl end!extid:",$exitid,"\tstatus:",$status,"\n";
}
//任务总量控制
if($task >= $taskNum) {
echo "taskNum enough!\n";
break;
}
}
//processid=0为新创建的进程
else{
//模拟不同任务的不同执行时长
$sleep = rand(1, 5);
$currentProcessid = posix_getpid(); //当前进程的Id
$parentProcessid = posix_getppid(); // 父级进程的ID
$phpProcessid = getmypid(); //当前php进程的id
echo "task:",$task,"\tprocessid:",$processid,"\tcurrentProcessid:",$currentProcessid,"\tparentProcessid:",$parentProcessid,"\tphpProcessid:",$phpProcessid,"\tsleep:",$sleep,"\tbegin!\n";
sleep($sleep);
echo "task:",$task,"\tprocessid:",$processid,"\tcurrentProcessid:",$currentProcessid,"\tparentProcessid:",$parentProcessid,"\tphpProcessid:",$phpProcessid,"\tsleep:",$sleep,"\tend!\n";
exit(0); //子进程执行完后退出,防止进入循环创建子进程
}
}
执行的结果:
task:1 processid:32225 currentProcessid:32224 parentProcessid:15053 phpProcessid:32224
task:0 processid:0 currentProcessid:32225 parentProcessid:32224 phpProcessid:32225 sleep:5 begin!
task:2 processid:32226 currentProcessid:32224 parentProcessid:15053 phpProcessid:32224
wait chl start!
task:1 processid:0 currentProcessid:32226 parentProcessid:32224 phpProcessid:32226 sleep:2 begin!
task:1 processid:0 currentProcessid:32226 parentProcessid:32224 phpProcessid:32226 sleep:2 end!
wait chl end!extid:32226 status:0
task:3 processid:32228 currentProcessid:32224 parentProcessid:15053 phpProcessid:32224
wait chl start!
task:2 processid:0 currentProcessid:32228 parentProcessid:32224 phpProcessid:32228 sleep:1 begin!
task:2 processid:0 currentProcessid:32228 parentProcessid:32224 phpProcessid:32228 sleep:1 end!
wait chl end!extid:32228 status:0
task:4 processid:32229 currentProcessid:32224 parentProcessid:15053 phpProcessid:32224
wait chl start!
task:3 processid:0 currentProcessid:32229 parentProcessid:32224 phpProcessid:32229 sleep:2 begin!
task:0 processid:0 currentProcessid:32225 parentProcessid:32224 phpProcessid:32225 sleep:5 end!
wait chl end!extid:32225 status:0
task:5 processid:32270 currentProcessid:32224 parentProcessid:15053 phpProcessid:32224
wait chl start!
task:4 processid:0 currentProcessid:32270 parentProcessid:32224 phpProcessid:32270 sleep:1 begin!
task:3 processid:0 currentProcessid:32229 parentProcessid:32224 phpProcessid:32229 sleep:2 end!
wait chl end!extid:32229 status:0
task:6 processid:32271 currentProcessid:32224 parentProcessid:15053 phpProcessid:32224
wait chl start!
task:5 processid:0 currentProcessid:32271 parentProcessid:32224 phpProcessid:32271 sleep:4 begin!
task:4 processid:0 currentProcessid:32270 parentProcessid:32224 phpProcessid:32270 sleep:1 end!
wait chl end!extid:32270 status:0
task:7 processid:32273 currentProcessid:32224 parentProcessid:15053 phpProcessid:32224
wait chl start!
task:6 processid:0 currentProcessid:32273 parentProcessid:32224 phpProcessid:32273 sleep:1 begin!
task:6 processid:0 currentProcessid:32273 parentProcessid:32224 phpProcessid:32273 sleep:1 end!
wait chl end!extid:32273 status:0
task:8 processid:32274 currentProcessid:32224 parentProcessid:15053 phpProcessid:32224
wait chl start!
task:7 processid:0 currentProcessid:32274 parentProcessid:32224 phpProcessid:32274 sleep:2 begin!
task:5 processid:0 currentProcessid:32271 parentProcessid:32224 phpProcessid:32271 sleep:4 end!
task:7 processid:0 currentProcessid:32274 parentProcessid:32224 phpProcessid:32274 sleep:2 end!
wait chl end!extid:32274 status:0
task:9 processid:32277 currentProcessid:32224 parentProcessid:15053 phpProcessid:32224
wait chl start!
wait chl end!extid:32271 status:0
task:8 processid:0 currentProcessid:32277 parentProcessid:32224 phpProcessid:32277 sleep:2 begin!
task:10 processid:32278 currentProcessid:32224 parentProcessid:15053 phpProcessid:32224
wait chl start!
task:9 processid:0 currentProcessid:32278 parentProcessid:32224 phpProcessid:32278 sleep:2 begin!
task:8 processid:0 currentProcessid:32277 parentProcessid:32224 phpProcessid:32277 sleep:2 end!
task:9 processid:0 currentProcessid:32278 parentProcessid:32224 phpProcessid:32278 sleep:2 end!
wait chl end!extid:32277 status:0
taskNum enough
执行分析:
- 在pcntl_fork出创建子进程后,子进程执行功能代码,父进程继续递增任务id,创建下一个任务进程;
- 通过pcntl_wait等待有子进程执行完毕退出后,再新创建进程,实现进程总数的控制;
- 在主进程完成创建后,通过break退出循环。此时可能有子进程继续执行。
相关函数:
pcntl_fork
在当前进程当前位置产生分支(子进程)。成功时,在父进程执行线程内返回产生的子进程的PID,在子进程执行线程内返回0。失败时,在 父进程上下文返回-1,不会创建子进程,并且会引发一个PHP错误。
pcntl_wait
等待或返回fork的子进程状态。wait函数刮起当前进程的执行直到一个子进程退出或接收到一个信号要求中断当前进程或调用一个信号处理函数。 如果一个子进程在调用此函数时已经退出(俗称僵尸进程),此函数立刻返回。子进程使用的所有系统资源将 被释放。
其他:
1.僵尸进程及孤儿进程的问题
部分僵尸进程被pcntl_wait获取状态并释放资源,未接管的进程在主进程退出后成为孤儿进程。孤儿进程被init进程收养,完成wait的状态获取和资源释放。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。