使用多线程运行PHP (tesseract)


Run PHP with multithreading (tesseract)

我需要通过tesseract发送一些图像,为了节省时间,我想并行运行tesseract多达6个实例。

我看了这个问题,但不能真正弄清楚如何编写代码

如何在PHP应用中使用多线程

从数据库中获取所有图像,并将结果连同与图像相关的其余信息一起写回数据库中的特定行

谁能链接到一个例子,或者谁能写一个关于如何做这项工作的快速例子?

当一个进程完成时,必须启动一个新的进程,因此总是有多达6个进程同时运行?

<标题> 更新
class Command {
    private $descriptorspec;
    
    private $output = '';
    
    public function __construct(){
        $this->descriptorspec = [
            0 => ['pipe', 'r'], // stdin
            1 => ['pipe', 'w'], // stdout
            2 => ['pipe', 'w'], // stderr
        ];
    }
    
    public function output(): string{
        return $this->output;
    }
    
    public function exec(string $syntax): string{
        $process = proc_open($syntax, $this->descriptorspec, $pipes);
        
        $this->output = stream_get_contents($pipes[1]);
        fclose($pipes[1]);
        
        $stderr = stream_get_contents($pipes[2]);
        fclose($pipes[2]);
        
        proc_close($process);
        
        return $stderr;
    }
}
$Cmd = new Command;
$Cmd->exec('tesseract ...');

不要这么做。PHP对多线程的支持非常糟糕。相反,应该使用多处理。使用proc_open &Co .——http://php.net/manual/en/function.proc-open.php

不需要使用多线程。要运行6个worker,而不需要与父进程同步—您可以使用proc_open

多线程更快,占用更少的资源(没有单独的命名空间),并且你可以运行它们比分支多4倍,但是多线程需要用非zts构建PHP(一些扩展不能用非zts),并且需要一些你能理解pthread模型的东西。

比如:

我们用proc_open创建了6个worker, Base进程监听die子进程(我使用我的包装器,使用Ev li或Event lib或没有它们)(child-processes),也许你喜欢包装器reactphp (child-processes)

    $child = new ChildProcesses();
    $child->add('<system command>');
    $child->add('<system command>');
    $child->add('<system command>');
    $child->add('<system command>');
    $child->add('<system command>');
    $fails = $child->check(null, function(ChildProcess $process) {
        echo 'Error with chld process';
    });

或者使用pthread读取官方文档。您需要在非zts中重新编译PHP,并安装pthread扩展。对于您的问题,我会使用Pool

您需要查看本页中的第一个示例Pool pthreads

更新:

如果你需要所有的时间-六个工人。您需要创建6个侦听器。而进程之间的通信使用zmq或rabbitmq、gearman或其他不同的队列。你的进程永远不会消亡,而倒下的人会被监督抬起来。

例如:

$loop = Factory::create();
$context = new Context($loop));
$context->getSocket('ZMQ::SOCKET_SUB);
$context->connect($host);
$context->subscribe('you_queue');
$context->on('messages', function($messages){
    // get specific data and run operation
});
$loop->run();

小心,zmq不是队列

  1. 不保存消息
  2. react/zmq使用EventLib,所以实际上我的例子将是异步的。

你需要使用Gearman或RabbitMQ -它们有理想的功能来完成你的任务


的问候马克西姆

我写了一个例子(基于子进程)。这应该可以解决您的问题:

这是parent.php:

$child = new ChildProcesses();
$child->addProcessInstance(new 'TkachInc'ChildProcesses'ChildProcess('php worker.php -w1'));
$child->addProcessInstance(new 'TkachInc'ChildProcesses'ChildProcess('php worker.php -w2'));
$child->addProcessInstance(new 'TkachInc'ChildProcesses'ChildProcess('php worker.php -w3'));
$child->addProcessInstance(new 'TkachInc'ChildProcesses'ChildProcess('php worker.php -w4'));
$child->addProcessInstance(new 'TkachInc'ChildProcesses'ChildProcess('php worker.php -w5'));
$child->addProcessInstance(new 'TkachInc'ChildProcesses'ChildProcess('php worker.php -w6'));
$child->daemon();

和您的worker.php(我添加了示例输出,您需要删除它):

$options = getopt("w:");
if(isset($options['w']))
{
    echo $options['w'].PHP_EOL;
    switch ($options['w'])
    {
        case "1":
            sleep(5);
            break;
        case "2":
            sleep(5);
            break;
        case "3":
            sleep(7);
            break;
        case "4":
            sleep(5);
            break;
        case "5":
            sleep(7);
            break;
        case "6":
            sleep(5);
            break;
    }
}
// your logic to receive from database and write to database

问候格言