多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
##进程管理模块## ---------- ` <?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