PHP的多进程模型-fork实现

本文介绍了一种在PHP中实现多进程处理数据的方法,通过自定义类简化了多进程任务的分配与执行流程,并提供了一个具体的实例说明如何使用该类进行批量数据处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

初始化一个多进程模型:$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);
        }
    }
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值