我需要通过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不是队列
- 不保存消息
- 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
问候格言