I really appreciate Mark Biek's answer. In fact I wrote a little script to show it in action:
message.php:
$arg1 = $argv[1];
$arg2 = $argv[2];
sleep($arg2*2);
print "Hello world $arg1 $arg2\n";
threads.php:
$pidIJs = array();
for ($i=0; $i<5; $i++)
{
for ($j=0; $j<5; $j++)
{
$cmd = "php message.php $i $j";
$outputFile = "threads-out.txt";
print "Launching $cmd ... ";
$pid = exec(sprintf("%s >> %s 2>&1 & echo $!", $cmd, $outputFile));
print "pid: $pid\n";
$pidIJs[$pid] = array($i, $j);
}
}
function isRunning($pid)
{
$result = shell_exec(sprintf("ps %d", $pid));
if (count(preg_split("/\n/", $result)) > 2) {
return true;
}
}
$pids = array_keys($pidIJs);
while (sizeof($pids) > 0)
{
$endedPids = array();
foreach($pids as $pid)
{
if (!isRunning($pid))
{
$ij = $pidIJs[$pid];
print("message.php $ij[0] $ij[1] has completed.\n");
array_push($endedPids, $pid);
}
}
$pids = array_diff($pids, $endedPids);
}
Slight difference in the exec
command, I'm sending PID to standard output instead of to a file so we can attach it to an i/j combination.
This code will loop from 0 to 4, and then 0 to 4 internally, running the message.php
script with arguments of $i
and $j
.
message.php will sleep for $j*2
seconds, and then print Hello World $i $j
.
Running threads.php, you can see it fire off the messages.php
script in the order of (0,0)
, (0,1)
, ... (0,4)
, (1,0)
, (1,1)
, ... (4,4)
, but then when testing the PID status, we see each process terminate in the order: (0,0)
, (1,0)
, ..., (4,0)
, (0,1)
, (1,1)
, (2,1)
, ..., (4,4)
.
This is because it takes $j*2
seconds for each messages.php
thread to run. So you get back all of the $j=0
threads first, then all the $j=1
threads, etc.