我正在尝试使用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服务器前端执行的代码,那么您需要重新思考您的体系结构