PHP的多进程模型-fork实现

来源:互联网 发布:mac安装aptget 编辑:程序博客网 时间:2024/05/23 21:57

在工作中,经常会用到将一大批数据分到多个进程中去处理的需求。于是自己写了一个简单的多进程类。方便以后使用,特在此总结一下:

初始化一个多进程模型:$processes = new Processes($processNumber); 

$processNumber表示启动几个进程。

用多进程模型来运行指定的方法:$processes->run($object, $method, $data, $recall)

$object:  要运行的方法所处的对象

$method:要运行的对象的方法

$data:要处理的数据,必须为一个数组

$recall:回调的方法


注:此类库模型仅在Linux平台下可用。且安装php时必须--enable-pcntl。即已安装pcntl模块。


例如:我们要对0-100个数都做加1操作,我们启动五个进程,则有如下代码:

class Add {    public function run()    {        $data = array();        for ($i = 0; $i <= 10; $i++) {           $data[] = $i;        }        $processes = new Processes(5);        $processes->run($this, 'add', $data);    }    public function add($data)    {        foreach ($data as $row) {            echo ($row+1).PHP_EOL;        }    }}$add = new Add();$add->run();


附:多进程模型类代码:


class Processes{    /**     * 进程的个数     *     * @var intval     */    protected $_number;    /**     * 已启动的进程个数     *     * @var intval     */    protected $_forkedNumber;    /**     * 最大进程个数     *     * @var intval     */    protected $_maxNumber;    /**     * 进程id列表     *     * @var array     */    protected $_pids;    /**     * 初始化     *     * @param intval $maxNumber     * @return void     */    public function __construct($maxNumber)    {        if ($maxNumber <= 1) {            throw new Exception('The num must above one');        }        $this->_forkedNumber = 0;        $this->_number       = 0;        $this->_maxNumber    = $maxNumber;    }    /**     * 获取进程的个数     *     * @return intval     */    public function getNumber()    {        return $this->_number;    }    /**     * 获取进程的个数     *     * @return intval     */    public function getForkedNumber()    {        return $this->_forkedNumber;    }    /**     * 获取最大进程的个数     *     * @return intval     */    public function getMaxNumber()    {        return $this->_maxNumber;    }    /**     * 设置最大进程个数     *     * @return intval     */    public function setMaxNumber($number)    {        $this->_maxNumber = $number;    }    /**     * 是否满了     *     * @return void     */    public function isFull()    {        return $this->getForkedNumber() >= $this->getMaxNumber();    }    /**     * 开始工作     *     * @param object $model     * @param string $command     * @param array $data     * @param string $recall     * @return void     */    public function run($model, $command, $data = array(), $recall = null)    {        if (!empty($data)) {            $data = array_chunk($data, ceil(count($data)/$this->getMaxNumber()), true);            $this->setMaxNumber(count($data));        }        for ($i = 0; $i < $this->getMaxNumber(); $i++) {            $pid  = pcntl_fork();            if ($pid < 0) {                return false;            } elseif ($pid == 0) {                $model->$command($data[$i]);                exit(0);            } else {                $this->_pids[$pid] = true;                $this->_number++;                $this->_forkedNumber++;            }        }        if ($this->isFull()) {            $this->wait();            if ($recall) {                $model->$recall();            }            exit(0);        }    }    /**     * 等候子进程运行完程序     *     * @return void     */    public function wait()    {        $finNumber  = 0;        $errNumber  = 0;        while (true) {            $pid = pcntl_waitpid(-1, $state, WNOHANG|WUNTRACED);            if ($pid <= 0) {                usleep(100);                continue;            }            $finNumber++;            $this->_number--;            if ($this->_number <= 0) {                return true;            }            usleep(100);        }    }}


原创粉丝点击