在php中使用pthread进行后台处理


Background Processing using pthread in php

我正在尝试使用pthread在php中实现多线程发送电子邮件。这里的基本思想是将电子邮件作为后台工作发送,这样用户就不必等待任务完成。

我有一项服务,用户PHPMailer发送电子邮件和它的工作良好。我正在使用以下代码进行多线程

class ThreadWorkerService extends 'Thread {
    private $_runMethod;
    private $_vars;
    private $_autoloderPath;
    function __construct($vars) {
        $this->_vars = $vars;
        $reflector = new 'ReflectionClass('Composer'Autoload'ClassLoader');
        $dir = dirname($reflector->getFileName());
        $this->_autoloderPath = $dir . "/../autoload.php";
    }
    public function setRunMethod($method) {
        $this->_runMethod = $method;
    }
    public function run() {
        if (!class_exists('Composer'Autoload'ClassLoader')) {
            if (file_exists($this->_autoloderPath )) {
                require_once( $this->_autoloderPath );
            } else {
                echo "autoloder not found";
            }
        }
        $method = $this->_runMethod;
        $results = $method($this->_vars);
    }
}

$storage = new 'Threaded();
$storage['emails'] = $emailArray;
$storage['config'] = $config;
$threadWorker = new ThreadWorkerService($storage);
$threadWorker->setRunMethod(function ($vars) {
    $emailArray = $vars['emails'];
    $config = $vars['config'];
    $emailService = new 'MyServices'EmailService($config);
    $emailService->sendAllEmails(true, $emailArray);
    }
});
$threadWorker->start(PTHREADS_INHERIT_CONSTANTS);

这里的问题是,如果我不使用,胎面剂量就不会执行

$threadWorker->join();

这消除了在这种情况下多线程的全部目的,我想知道的是,即使在父进程完成的情况下,是否有可能保持子线程的活力。我甚至试过把线拆开,但没有成功。

我熟悉如何使用RabbitMQ等消息服务,但我希望保持应用程序的独立性。

这里的问题是,如果我不使用:$threadWorker->join();,线程就不会执行,这就消除了在这种情况下多线程的全部目的。

这种情况很可能是主线程的stdout或其他依赖项在线程执行之前被关闭或销毁。

摘自Thread:的PHP手册

警告: 依赖引擎来确定线程何时应该加入可能会导致不良行为;程序员应该尽可能明确

您不需要立即加入,但建议显式加入。

下面的示例代码说明了这个问题:

<?php
class Test extends Thread {
    public function run() {
        sleep(1);
        echo "Thread'n";
    }
}
$test = new Test();
$test->start();
echo "End'n";
?>

如果CPU速度允许,主上下文将在Thread到达echo之前开始破坏Thread

你通常会得到输出:

End
Thread

然而,如果代码更复杂,例如,操作Thread构造函数中设置的依赖项的代码,则这些依赖项在使用时可能已经被破坏。

对隐式join进行了最后的尝试(在pthreads的最新版本中),但您不能依赖于与您的期望兼容的销毁顺序,因此显式join更可取。

值得注意的是:pthreads的最新版本(PHP7+)禁止在CLI之外的任何地方执行;如果这是在web服务器前端执行的代码,那么您需要重新思考您的体系结构