##進程管理模塊##
----------
`
<?php
$worker_num =2;//創建的進程數
for($i=0;$i<$worker_num ; $i++){
$process = new swoole_process('callback_function_we_write');
$pid = $process->start();
echo PHP_EOL . $pid;//
}
function callback_function_we_write(swoole_process $worker){
echo PHP_EOL;
var_dump($worker);
echo PHP_EOL;
}
`
介紹看這里 [swoole的process][1]
大家可以先看看自己的swoole版本,在命令行里面敲
> php --ri swoole
更多的php命令行使用,大家學習 [php命令行參數][2]
ok 我們直奔主題
**怎么用**
多進程的創建
----------
不多說,直接上代碼
```
<?php
$worker_num =2;//創建的進程數
for($i=0;$i<$worker_num ; $i++){
$process = new swoole_process('callback_function_we_write');
$pid = $process->start();
echo PHP_EOL . $pid;//
}
function callback_function_we_write(swoole_process $worker){
echo PHP_EOL;
var_dump($worker);
echo PHP_EOL;
}
```
運行結果如下
```
5445
object(swoole_process)#1 (3) {
["pipe"]=>
int(3)
["callback"]=>
string(26) "callback_function_we_write"
["pid"]=>
int(5445)
}
5446
object(swoole_process)#2 (3) {
["pipe"]=>
int(5)
["callback"]=>
string(26) "callback_function_we_write"
["pid"]=>
int(5446)
}
```
可以看到,我們使用 new swoole_process 創建進程,這里需要一個參數,也就是回調函數
當我們使用 $process->start()執行后,返回這個進程的pid ,也就是 $pid.
此時子進程啟動,調用回調函數,并傳一個參數 也就是 swoole_process 類型的 $worker
我故意輸出了 $worker 看看里面有什么,結果有三個屬性
> pipe 進程的管道id 這個等說道進程間通信的時候再聊
> pid 就是當前子進程的 pid 啦
> callback 這個是我們自己寫的回調函數名
到這里,我們就可以用多線程玩耍了,
比如,我們可以測試多線程的運行速度
```
<?php
echo PHP_EOL . time() ;
$worker_num =3;//創建的進程數
for($i=0;$i<$worker_num ; $i++){
$process = new swoole_process('callback_function_we_write');
$pid = $process->start();
}
function callback_function_we_write(swoole_process $worker){
for($i=0;$i<100000000;$i++){}
echo PHP_EOL . time() ;
}
```
我本機運行結果
> 1435563435 // 開始時間
> 1435563438 //線程1 結束時間
> 1435563440 //線程2 結束時間
> 1435563440 //線程3 結束時間
算三次 用了5s (其實一般是4s)
再玩一次
```
<?php
echo PHP_EOL . time() ;
for($i=0;$i<100000000;$i++){}
for($i=0;$i<100000000;$i++){}
for($i=0;$i<100000000;$i++){}
echo PHP_EOL . time() ;
```
我本機運行結果
> 1435563704
> 1435563712
這次用了8s
做了這些,我想說明一個問題
> **并不是說 單線程 要花8s 做完的活,我們用3個線程就能將時間縮小三倍了**
嘛,因為這是我以前的誤區
**多線程還可以這樣玩**
```
<?php
$funcMap=array('methodOne' , 'methodTwo' ,'methodThree' );
$worker_num =3;//創建的進程數
for($i=0;$i<$worker_num ; $i++){
$process = new swoole_process($funcMap[$i]);
$pid = $process->start();
sleep(2);
}
while(1){
$ret = swoole_process::wait();
if ($ret){// $ret 是個數組 code是進程退出狀態碼,
$pid = $ret['pid'];
echo PHP_EOL."Worker Exit, PID=" . $pid . PHP_EOL;
}else{
break;
}
}
function methodOne(swoole_process $worker){// 第一個處理
echo $worker->callback .PHP_EOL;
}
function methodTwo(swoole_process $worker){// 第二個處理
echo $worker->callback .PHP_EOL;
}
function methodThree(swoole_process $worker){// 第三個處理
echo $worker->callback .PHP_EOL;
}
```
我多加的sleep是為了運行時看得更清楚,你也可以去掉
這里我使用了 swoole_process::wait() [詳解][3]
目的是當子進程結束后,主進程能夠知道。
我們來想一個情景
過節了,媽媽要做飯,一看廚房里缺了 油,鹽,糖,味精,十三香。于是吩咐兒子去小賣部買點回來。廚房這邊也不能閑著,老媽要繼續洗菜,切菜。等到調料買回來了,菜也洗好,切好了,開始炒,這邊炒好了一個菜,就要立刻送到餐桌上。
這個情景里面,顯然使用了多進程,并且各進程做的不是同樣的事情。當子進程都完成了,主進程開始繼續業務。
現在有了一個問題,就拿上面的情景來說,兒子去買調味料,如果發現鹽沒有了,或者錢不夠了怎么辦,如何與媽媽聯系呢? 這就是下面要說的 **進程間的通信**
進程間的通信
----------
Process 的通信方式有兩種
> 管道
> swoole_process->write(string $data);
> swoole_process->read(int $buffer_size=8192);
>
> 消息隊列
> swoole_process->useQueue();
> swoole_process->push(string $data);
> swoole_process->pop(int $maxsize = 8192);
我們先說說管道
管道通訊
----------
這里我們要再次的提及進程的創建 new swoole_process
大家請看這里 [進程的創建][4]
第一個參數是回調函數,不說了
第二個參數含義等會我會結合例子來說
第三個參數是默認的 true,意思是創建管道,大家還記得回調函數里我特意將$worker輸出看到的內容嗎?
```
object(swoole_process)#1 (3) {
["pipe"]=>
int(3)
["callback"]=>
string(26) "callback_function_we_write"
["pid"]=>
int(5445)
}
```
關鍵是這里的 **pipe** 這個就是本進程的管道id
我們可以這樣理解
> 每次創建一個進程后,就會隨之創建一個管道,主進程想和哪一個進程通信,就向那個進程的管道寫入/讀取數據。
ok,我們看看代碼
```
<?php
$redirect_stdout = false;// 重定向輸出 ; 這個參數用途等會我們看效果
$worker_num = 2;//線程數量
$workers = [];//存放進程用的
for($i = 0; $i < $worker_num; $i++){
$process = new swoole_process('workerFunc',$redirect_stdout );
$pid = $process->start();
$workers[$pid] = $process;//將每一個進程的句柄存起來
}
// 這里是主進程哦。
foreach($workers as $pid => $process){// $process 是子進程的句柄
$process->write("hello worker[$pid]\n");//子進程句柄向自己管道里寫內容 $process->write($data);
echo "From Worker: ".$process->read();//子進程句柄從自己的管道里面讀取信息 $process->read();
echo PHP_EOL.PHP_EOL;
}
function workerFunc(swoole_process $worker){//這里是子進程哦
$recv = $worker->read();
echo PHP_EOL. "From Master: $recv\n";
//send data to master
$worker->write("hello master , this pipe is ". $worker->pipe ."; this pid is ".$worker->pid."\n");
sleep(2);
$worker->exit(0);
}
```
貼上運行結果
```
From Master: hello worker[8205]
From Worker: hello master , this pipe is 3; this pid is 8205
From Master: hello worker[8206]
From Worker: hello master , this pipe is 5; this pid is 8206
```
[1]: http://wiki.swoole.com/wiki/page/213.html
[2]: http://php.swoole.com/wiki/PHP%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0
[3]: http://wiki.swoole.com/wiki/page/220.html
[4]: http://wiki.swoole.com/wiki/page/214.html