深入解析PHP中的(偽)多線程與多進程(2)_PHP教程
推薦:php 常用算法和時間復(fù)雜度本篇文章是對php中的常用算法以及時間復(fù)雜度進行了詳細的分析介紹,需要的朋友參考下 按數(shù)量級遞增排列,常見的時間復(fù)雜度有:常數(shù)階O(1),對數(shù)階O(log2n),線性階O(n),線性對數(shù)階O(nlog2n),平方階O(n2),立方階O(n3) 復(fù)制代碼 代碼如下: //二分查找O(log2n) function erf
[文章二] 嘗試php命令行腳本多進程并發(fā)執(zhí)行
除了fork, cli下的并發(fā)方式還有一種,看我的例子:
php不支持多線程,但是我們可以把問題轉(zhuǎn)換成“多進程”來解決。由于php中的pcntl_fork只有unix平臺才可以使用,所以本文嘗試使用popen來替代。
下面是一個例子:
被并行調(diào)用的子程序代碼:
<?php
if($argc==1){
echo("argv\n");
}
$arg = $argv[1];
for($i=0; $i<10; $i++)
{
echo($i.".1.".time()." exec $arg \n");
if($arg=='php2'){
sleep(1);
echo($i.".2.".time()." exec $arg \n");
sleep(1);
}else{
sleep(1);
}
}
?>
主調(diào)用者程序,由他調(diào)用子進程,同時并發(fā)的收集子程序的輸出
error_reporting(E_ALL);
$handle1 = popen('php sub.php php1', 'r');
$handle2 = popen('php sub.php php2', 'r');
$handle3 = popen('php sub.php php3', 'r');
echo "'$handle1'; " . gettype($handle1) . "\n";
echo "'$handle2'; " . gettype($handle2) . "\n";
echo "'$handle3'; " . gettype($handle3) . "\n";
//sleep(20);
while(!feof($handle1) || !feof($handle2) || !feof($handle3) )
{
$read = fgets($handle1);
echo $read;
$read = fgets($handle2);
echo $read;
$read = fgets($handle3);
echo $read;
}
pclose($handle1);
pclose($handle2);
pclose($handle3);
下面是我機器上的輸出:
C:\my_hunter>php exec.php
'Resource id #4'; resource
'Resource id #5'; resource
'Resource id #6'; resource
0.1.1147935331 exec php1
0.1.1147935331 exec php2
0.1.1147935331 exec php3
1.1.1147935332 exec php1
0.2.1147935332 exec php2
1.1.1147935332 exec php3
2.1.1147935333 exec php1
1.1.1147935333 exec php2
2.1.1147935333 exec php3
3.1.1147935334 exec php1
1.2.1147935334 exec php2
3.1.1147935334 exec php3
4.1.1147935335 exec php1
2.1.1147935335 exec php2
4.1.1147935335 exec php3
5.1.1147935336 exec php1
2.2.1147935336 exec php2
5.1.1147935336 exec php3
6.1.1147935337 exec php1
3.1.1147935337 exec php2
6.1.1147935337 exec php3
7.1.1147935338 exec php1
3.2.1147935338 exec php2
7.1.1147935338 exec php3
8.1.1147935339 exec php1
4.1.1147935339 exec php2
8.1.1147935339 exec php3
9.1.1147935340 exec php1
4.2.1147935340 exec php2
9.1.1147935340 exec php3
5.1.1147935341 exec php2
5.2.1147935342 exec php2
6.1.1147935343 exec php2
6.2.1147935344 exec php2
7.1.1147935345 exec php2
7.2.1147935346 exec php2
8.1.1147935347 exec php2
8.2.1147935348 exec php2
9.1.1147935349 exec php2
9.2.1147935350 exec php2
**總結(jié):**
**主程序循環(huán)等待子進程, 通過fgets或fread 把子進程的輸出獲取出來 , 從時間戳上看,的確實現(xiàn)了并發(fā)執(zhí)行。**
-----------------------------------------------
以后的改進:
* popen打開的句柄是單向的,如果需要向子進程交互,可以使用proc_open
* 使用數(shù)組和子函數(shù)代替while(!feof($handle1)|| !feof($handle2) || !feof($handle3) )這種齷齪的寫法
* 用fread一次把子進程已經(jīng)產(chǎn)生的輸出取完,而不是每次一行。
一個并發(fā)執(zhí)行shell任務(wù)的調(diào)度者,本程序讀取一個任務(wù)文件,把里面的每行命令并發(fā)執(zhí)行, 可以設(shè)置同時存在的子進程數(shù)目:
/*
主任務(wù)管理器
并發(fā)的執(zhí)行子任務(wù)列表
*/
include("../common/conf.php");
include("../common/function.php");
//開啟的進程數(shù)
$exec_number = 40 ;
/***** main ********/
if($argc==1){
echo("argv\n");
}
$taskfile = $argv[1];
//tasklist
$tasklist = file($taskfile);
$tasklist_len = count($tasklist);
$tasklist_pos = 0;
$handle_list = array();
while(1)
{
//子進程列表有空閑,則填充補齊子進程列表
if($exec_number > count($handle_list) &&
$tasklist_pos < $tasklist_len)
{
for($i=$tasklist_pos; $i<$tasklist_len; )
{
$command = $tasklist[$i] ;
$handle_list[] = popen($command , "r" );
tolog("begin task \t ".$tasklist[$i]);
$i++;
if($exec_number == count($handle_list)) break;
}
$tasklist_pos = $i;
}
//如果子進程列表空,退出
if(0 == count($handle_list))
{
break;
}
//檢查子進程列表的輸出,把停掉的子進程關(guān)閉并記錄下來
$end_handle_keys = array();
foreach($handle_list as $key => $handle)
{
//$str = fgets($handle, 65536);
$str = fread($handle, 65536);
echo($str);
if(feof($handle))
{
$end_handle_keys[] = $key;
pclose($handle);
}
}
//踢出停掉的子進程
foreach($end_handle_keys as $key)
{
unset($handle_list[$key]);
//var_dump($handle_list);
//exit;
}
}
tolog("\n\n*******************end**********************\n\n", "" , true);
附加一段Socket多進程接收的代碼:
分享:解析PHP跳出循環(huán)的方法以及continue、break、exit的區(qū)別介紹PHP中的循環(huán)結(jié)構(gòu)大致有for循環(huán),while循環(huán),do{} while 循環(huán)以及foreach循環(huán)幾種,不管哪種循環(huán)中,在 PHP中跳出循環(huán)大致有這么幾種方式: 代碼: 復(fù)制代碼 代碼如下: ?php $i = 1; while (true) { // 這里看上去這個循環(huán)會一直執(zhí)行 if ($i==2) {// 2跳過不顯示 $i++;
- 相關(guān)鏈接:
- 教程說明:
PHP教程-深入解析PHP中的(偽)多線程與多進程(2)
。