简单多进程任务处理程序

Posted qixidi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简单多进程任务处理程序相关的知识,希望对你有一定的参考价值。


简单多进程任务处理程序


<?php

/**
 * 多进程任务处理辅助类
 */
class TaskHelper{
  /**
     * worker进程最大数量, 至少两个
     */
    protected $maxProcess;
    
    /**
     * 动态参数,设置为 0 表示不使用自适应进程方式
     */
    protected $dynamicParam;
    
    /**
     * 任务的实际处理者,对象, 必须有 runWorker 方法
     */
    protected $worker;
    
    public function __construct($worker, $maxProcess = 4, $dynamicParam = 0) {
        $this->worker = $worker;
        $this->maxProcess = max(2, (int)$maxProcess);
        $this->dynamicParam = max(0, (int)$dynamicParam);
    }
    
    /**
     * fork子进程处理数据
     * @param Array $data 需要处理的数据,必须是数组
     */
    public function run(&$data) {
        $count = count($data);
        
        // 需要开启的子进程数
        $num = $this->dynamicParam ? min( $this->maxProcess, ceil($count / $this->dynamicParam) ) : $this->maxProcess;
        
        // 每个进程处理的数据量
        $n = ceil($count / $num); 
        
        $childs = array();
        
        for($i = 0; $i < $count; $i += $n) {
            $pid = pcntl_fork();
            if($pid == -1) {
                echo "Fork worker failed!";
                return false;
            }
            
            if($pid) {
                echo "Fork worker success! pid:",  $pid, "
";
                $childs[] = $pid;
            } else {
                $sliceData = array_slice($data, $i, $n);
    
                $this->worker->runWorker($sliceData);
                exit();
            }
        }
        
        $this->check($childs);
    }
    
    /**
     * 检测子进程状态,监控子进程是否退出,并防止僵尸进程
     */
    protected function check($childs) {
        while(true) {
            foreach($childs as $index => $pid) {
                $pid && $res = pcntl_waitpid($pid, $status, WNOHANG);
                if(!$pid || $res == -1) {
                    echo "End worker: $pid 
";
                    unset($childs[$index]);
                }
            }
            
            if(empty($childs)) break;
            sleep(1);
        }
    }
}

/**
 * 使用示例
 */
class Test {
    public function run() {
        $data = array_fill(0, 800, 1);
        
        // 开8个进程将 $data 分成8份,交由下面的 runWorker 方法处理
        $task = new TaskHelper($this, 8);
        
        $task->run($data); // 如果前面连接了数据库、redis等,最好在这之前关闭掉
    }
    
    /**
     * 这里编写代相应码来处理数据
     */
    public function runWorker($data) {
        // do something...
    }
}

$obj = new Test;
$obj->run();

以上是关于简单多进程任务处理程序的主要内容,如果未能解决你的问题,请参考以下文章

cpp►多线程

在 Python 多处理进程中运行较慢的 OpenCV 代码片段

vbstask方法

译文:18个实用的JavaScript代码片段,助你快速处理日常编程任务

EasyTask简单易用的PHP常驻内存多进程任务管理器

多个请求是多线程吗