文档章节

PHP多进程处理并行处理任务实例

rihgtzhao
 rihgtzhao
发布于 2014/06/21 16:12
字数 737
阅读 43
收藏 1

本文目的

本文通过例子讲解linux环境下,使用php进行并发任务处理,以及如何通过pipe用于进程间的数据同步。写得比较简单,作为备忘录。

PHP多进程

通过pcntl_XXX系列函数使用多进程功能。注意:pcntl_XXX只能运行在php CLI(命令行)环境下,在web服务器环境下,会出现无法预期的结果,请慎用!

管道PIPE

管道用于承载简称之间的通讯数据。为了方便理解,可以将管道比作文件,进程A将数据写到管道P中,然后进程B从管道P中读取数据。php提供的管道操作API与操作文件的API基本一样,除了创建管道使用posix_mkfifo函数,读写等操作均与文件操作函数相同。当然,你可以直接使用文件模拟管道,但是那样无法使用管道的特性了。

僵尸进程

子进程结束时,父进程没有等待它(通过调用wait或者waitpid),那么子进程结束后不会释放所有资源(浪费呀!),这种进程被称为僵尸进程,他里面存放了子进程结束时的相关数据,如果僵尸进程过多,会占用大量系统资源(如内存),影响机器性能。

代码

废话少说直接上代码

/**
  * this is a demo for php fork and pipe usage. fork use
  * to create child process and pipe is used to sychoroize
  * the child process and its main process.
  * @author bourneli
  * @date: 2012-7-6
  */
 
define( "PC" , 10); // 进程个数
define( "TO" , 4); // 超时
define( "TS" , 4); // 事件跨度,用于模拟任务延时
 
if  (!function_exists( 'pcntl_fork' )) {
     die ( "pcntl_fork not existing" );
}
 
// 创建管道
$sPipePath  = "my_pipe." .posix_getpid();
if  (!posix_mkfifo( $sPipePath , 0666)) {
     die ( "create pipe {$sPipePath} error" );
}
 
// 模拟任务并发
for  ( $i  = 0; $i  < PC; ++ $i  ) {
     $nPID  = pcntl_fork(); // 创建子进程
     if  ( $nPID  == 0) {
         // 子进程过程
         sleep(rand(1,TS)); // 模拟延时
         $oW  = fopen ( $sPipePath , 'w' );
         fwrite( $oW , $i . "\n" ); // 当前任务处理完比,在管道中写入数据
         fclose( $oW );
         exit (0); // 执行完后退出
     }
}
 
// 父进程
$oR  = fopen ( $sPipePath , 'r' );
stream_set_blocking( $oR , FALSE); // 将管道设置为非堵塞,用于适应超时机制
$sData  = '' ; // 存放管道中的数据
$nLine  = 0;
$nStart  = time();
while  ( $nLine  < PC && (time() - $nStart ) < TO) {
     $sLine  = fread ( $oR , 1024);
     if  ( empty ( $sLine )) {
         continue ;  
     }  
     
     echo  "current line: {$sLine}\n" ;
     // 用于分析多少任务处理完毕,通过‘\n’标识
     foreach ( str_split ( $sLine ) as  $c ) {
         if  ( "\n"  == $c ) {
             ++ $nLine ;
         }
     }
     $sData  .= $sLine ;
}
echo  "Final line count:$nLine\n" ;
fclose( $oR );
unlink( $sPipePath ); // 删除管道,已经没有作用了
 
// 等待子进程执行完毕,避免僵尸进程
$n  = 0;
while  ( $n  < PC) {
     $nStatus  = -1;
     $nPID  = pcntl_wait( $nStatus , WNOHANG);
     if  ( $nPID  > 0) {
         echo  "{$nPID} exit\n" ;
         ++ $n ;
     }
}
 
// 验证结果,主要查看结果中是否每个任务都完成了
$arr2  = array ();
foreach ( explode ( "\n" , $sData ) as  $i ) { // trim all
     if  ( is_numeric (trim( $i ))) {
         array_push ( $arr2 , $i ); 
     }
}
$arr2  = array_unique ( $arr2 );
if  ( count ( $arr2 ) == PC) { 
     echo  'ok' ;
} else  {
     echo   "error count "  . count ( $arr2 ) . "\n" ;
     var_dump( $arr2 );
}


ok,完毕,注释写的比较清除,执行结果如下:

clip_image002


本文转载自:

共有 人打赏支持
rihgtzhao
粉丝 6
博文 38
码字总数 2307
作品 0
丰台
程序员
私信 提问
如何修改当前多实例任务节点的处理人和参与人

@咖啡兔 你好,想跟你请教个问题:在多实例任务中,如何修改当前(串行或并行)多实例任务的任务处理人和参与人。如流程已经正常流转至串行多实例任务,部分参与人已经完成(审批)操作,此时...

雨棚一下-你就知道
2016/06/01
204
1
构建高性能J2EE应用的五种核心策略

对于J2EE,我们知道当开发应用时,在架构设计阶段的决定将对应用的性能和可扩展性产生深远的影响。现在当开发一个应用项目时,我们越来越多地注意到了性能和可扩展性的问题。应用性能的问题比...

青夜之衫
2017/12/05
0
0
一个简单的PHP多进程任务处理辅助类

有时遇到跑计划任务,单进程太慢的情况,需要多进程同时处理,这个类就是为了更方便的开启多进程处理数据而编写的。 https://git.oschina.net/664712890/codes/d65t89euxjyan4z0wf3hv38...

老陌
2016/11/25
513
0
《C#并发编程经典实例》学习笔记-第一章并发编程概述

并发编程的术语 并发 同时做多件事情 多线程 并发的一种形式,它采用多个线程来执行程序。 多线程是并发的一种形式,但不是唯一的形式。 并行处理 把正在执行的大量的任务分割成小块,分配给...

repeatedly
2018/08/18
0
0
PHP 的异步并行和协程 C 扩展 - Swoole

PHP的异步、并行、高性能网络通信引擎,使用纯C语言编写,提供了PHP语言的异步多线程服务器,异步TCP/UDP网络客户端,异步MySQL,异步Redis,数据库连接池,AsyncTask,消息队列,毫秒定时器...

matyhtf
2014/03/03
0
12

没有更多内容

加载失败,请刷新页面

加载更多

iOS个人中心渐变动画、微信对话框、标签选择器、自定义导航栏、短信验证输入框等源码

iOS精选源码 简单的个人中心页面-自定义导航栏并予以渐变动画 程序员取悦女票的正确姿势---Tip1(iOS美容篇) iOS 前台重启应用和清除角标的问题 微信原生提醒对话框3.0 JHLikeButton - 有趣...

Android爱开源
7分钟前
0
0
Yii2使用驼峰命名的形式访问控制器

yii2在使用的时候,访问控制器的时候,如果控制器的名称是驼峰命名法,那访问的url中要改成横线的形式。例如: public function actionRoomUpdate(){//}//访问的时候就要www.test.co...

dragon_tech
10分钟前
0
0
Navicat使用教程:使用Navicat Query Analyzer优化查询性能(第2部分)

下载Navicat Monitor最新版本 Navicat Monitor 是一套安全、简单而且无代理的远程服务器监控工具。它具有强大的功能使你的监控发挥最大效用。受监控的服务器包括 MySQL、MariaDB 和 Percona ...

电池盒
17分钟前
0
0
Python3 读写utf-8文本文件

with open('testRead.txt', 'r', encoding='utf-8') as f: for each_line in f: Passwith open('testWrite.txt', 'w', encoding='utf-8') as f: f.write('写入的内容'......

编程老陆
19分钟前
0
0
Linux syslog相关函数详解

介绍 syslog是Unix系统的日志系统。可以将日志记录在本地系统中。 一个完整的syslong日志包含如下信息:程序模块 | 严重性 | 时间 | 主机名 | 进程名 | 进程ID | 正文。 syslong相关函数 1....

RongJinhui0
24分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部