zoukankan      html  css  js  c++  java
  • PHP多进程编程

    PHP本身不支持多线程,多进程支持的也不是特别好,网上找到一份多进程代码(http://jasonyu.cn/html/2010/294.html),写了一个测试程序简单测了一下,可以运行,但是离上线还差得很远。

    <?php
    /**
     * Project: Signfork: php多线程库
     * File: Signfork.class.php
     */
    
    class Signfork{
        /**
         * 设置子进程通信文件所在目录
         * @var string
         */
        private $tmp_path='/tmp/';
    
        /**
         * Signfork引擎主启动方法
         * 1、判断$arg类型,类型为数组时将值传递给每个子进程;类型为数值型时,代表要创建的进程数.
         * @param object $obj 执行对象
         * @param string|array $arg 用于对象中的__fork方法所执行的参数
         * 如:$arg,自动分解为:$obj->__fork($arg[0])、$obj->__fork($arg[1])…
         * @return array 返回 array(子进程序列=>子进程执行结果);
         */
        public function run($obj,$arg=1){
            if(!method_exists($obj,'__fork')){
                exit('Method "__fork" not found!');
            }
    
            if(is_array($arg)){
                $i=0;
                foreach($arg as $key=>$val){
                    $spawns[$i]=$key;
                    $i++;
                    $this->spawn($obj,$key,$val);
                }
                $spawns['total']=$i;
            }elseif($spawns=intval($arg)){
                for($i = 0; $i < $spawns; $i++){
                    $this->spawn($obj,$i);
                }
            }else{
                exit('Bad argument!');
            }
    
            if($i>1000) exit('Too many spawns!');
            return $this->request($spawns);
        }
    
        /**
         * Signfork主进程控制方法
         * 1、$tmpfile 判断子进程文件是否存在,存在则子进程执行完毕,并读取内容
         * 2、$data收集子进程运行结果及数据,并用于最终返回
         * 3、删除子进程文件
         * 4、轮询一次0.03秒,直到所有子进程执行完毕,清理子进程资源
         * @param string|array $arg 用于对应每个子进程的ID
         * @return array 返回 array([子进程序列]=>[子进程执行结果]);
         */
        private function request($spawns){
            $data=array();
            $i=is_array($spawns)?$spawns['total']:$spawns;
            for($ids = 0; $ids<$i; $ids++){
                while(!($cid=pcntl_waitpid(-1, $status, WNOHANG)))usleep(30000);
                $tmpfile=$this->tmp_path.'sfpid_'.$cid;
                $data[$spawns['total']?$spawns[$ids]:$ids]=file_get_contents($tmpfile);
                unlink($tmpfile);
            }
            return $data;
        }
    
        /**
         * Signfork子进程执行方法
         * 1、pcntl_fork 生成子进程
         * 2、file_put_contents 将'$obj->__fork($val)'的执行结果存入特定序列命名的文本
         * 3、posix_kill杀死当前进程
         * @param object $obj 待执行的对象
         * @param object $i 子进程的序列ID,以便于返回对应每个子进程数据
         * @param object $param 用于输入对象$obj方法'__fork'执行参数
         */
        private function spawn($obj,$i,$param=null){
            if(pcntl_fork()===0){
                $cid=getmypid();
                file_put_contents($this->tmp_path.'sfpid_'.$cid,$obj->__fork($param));
                posix_kill($cid, SIGTERM);
                exit;
            }
        }
    }
    ?>

    测试程序如下:

    <?php
    require_once(dirname(__FILE__) . '/Signfork.class.php');
    class ExecObj{
        public function __fork($param){
            return getmypid();
        }
        
    }
    echo getmypid()."\n";
    $signfork = new Signfork();
    $result = $signfork->run(new ExecObj(),5);
    foreach ($result as $key=>$val)
    {
        echo $key." ".$val."\n";
    }
    ?>
  • 相关阅读:
    阻塞 io 非阻塞 io 学习笔记
    nodejs 不是单线程
    最短路径之迪杰斯特拉(Dijkstra)算法
    迷宫问题求解之“A*搜索”(二)
    迷宫问题求解之“穷举+回溯”(一)
    CnBlogs自定义博客样式
    .NET中Main函数使用小技巧
    .NET中的枚举(Enum)
    DotNetBar的使用—(界面风格)
    .NET4.5新特性async和await修饰符实现异步编程
  • 原文地址:https://www.cnblogs.com/end/p/2973881.html
Copyright © 2011-2022 走看看