PHP pthreads很奇怪

时间:2014-03-07 08:22:31

标签: php multithreading pthreads

抱歉我的英语扭曲了 - 这不是我的原生。

我遇到了麻烦:pthreads有效,但是以某种奇怪的方式:例如,我不能从一个线程做“回声”。
来自互联网的一些示例代码:   

<?php
    ini_set('display_errors',E_ALL);
    class hashThread extends Thread {
    private $max = 1;
    private $index = 0;
    function __construct($max, $index)
    {
        $this->max = $max;
        $this->index = $index;
    }
    public function run()
    {
        for ($i=1; $i<=$this->max; $i++)
        {
            md5($i);
        }
        error_log("Thread #{$this->index} finished\r\n");
        echo "Thread #{$this->index} finished\r\n";
    }
    }
    $thread_count = 8;
    $start_time = microtime(true);
    for($i=1; $i<=$thread_count; $i++)
    {
    $thread[$i] = new hashThread(1e6, $i);
    $thread[$i]->start(PTHREADS_INHERIT_NONE);
    }
    echo "Done in: " . round(microtime(true) - $start_time, 2) . " seconds";
?>

脚本只显示“完成:0.14秒”(在网页中),没有回音,但是!它出错了:

$ tail -f /var/log/nginx/error_log | grep Thread
2014/03/07 08:05:10 [error] 12621#0: *2818394 FastCGI sent in stderr: "PHP message: Thread #2 finished" ...
2014/03/07 08:05:10 [error] 12621#0: *2818394 FastCGI sent in stderr: "PHP message: Thread #1 finished" ...
2014/03/07 08:05:10 [error] 12621#0: *2818394 FastCGI sent in stderr: "PHP message: Thread #3 finished" ...
2014/03/07 08:05:10 [error] 12621#0: *2818394 FastCGI sent in stderr: "PHP message: Thread #6 finished" ...
2014/03/07 08:05:10 [error] 12621#0: *2818394 FastCGI sent in stderr: "PHP message: Thread #5 finished" ...
2014/03/07 08:05:10 [error] 12621#0: *2818394 FastCGI sent in stderr: "PHP message: Thread #7 finished" ...
2014/03/07 08:05:10 [error] 12621#0: *2818394 FastCGI sent in stderr: "PHP message: Thread #4 finished" ...
2014/03/07 08:05:10 [error] 12621#0: *2818394 FastCGI sent in stderr: "PHP message: Thread #8 finished" ...

实际上,我在我的线程中没有使用任何echo,我需要聚合一些webservices(每个webservice类=线程),等待最慢的线程,并将所有结果合并到一个可以从外部获取的数组,但我之前从未使用PHP或其他语言的线程。如果你给我一些例子,我将不胜感激。谢谢。

软件:
Gentoo x86
PHP 5.4.23(nginx配置为使用php-fpm)
Nginx 1.4.4

没有阿帕奇。 PHP构建了线程安全,启用了pthreads模块。

2 个答案:

答案 0 :(得分:2)

标准输出无法保证,Zend不提供API以确保您获得正确的流,它不能因为它所在的所有环境,它留给堆栈中PHP以上的软件,FPM确实如上所述在堆栈中,它使用stderr / stdout做了一些奇怪的事情 - 它必须完全工作。

所以,不要这样做!

如上所述,无论如何都不需要编写标准输出,如果你想记录,然后为文件写一个记录器:)

这是你的起点:

阅读该自述文件的文档部分中的文章。第一部分精确解释了pthreads如何存在以及它是如何工作的,并将为您提供良好的知识基础。

第二个描述了我们现在拥有的最高级别的线程,即Pooling,你可以跳过那个......我不会:)

请阅读,这将是非常有帮助的......

在您阅读和理解时,这是一个半相关的示例代码清单,它从几个位置获取页面并将结果存储在主线程可以处理的共享数组中:

<?php
/*
 Just a container class, nothing to see here
*/
class Store extends Stackable {
    public function run(){}
}

class Hash extends Thread {
    /*
    * Take shared storage and target for fetching
    */
    public function __construct(Store $store, $target) {
        $this->store = $store;
        $this->target = $target;
    }

    /*
    * Fetch contents of target and store associatively in Store
    */
    public function run() {
        $this->store[$this->target] = file_get_contents(
            $this->target);
    }

    protected $store;
    protected $target;
}

/* will hold shared data */
$store   = new Store();
/* will hold threads */
$threads = [];
$thread  = 0;

/* create and start all threads */
while ($thread < 4) {
    $threads[$thread] = new Hash($store, sprintf(
        "http://www.google.co.uk/?q=%s", md5(mt_rand()*microtime())));
    $threads[$thread]->start();
    $thread++;
}

/* join all threads */
foreach ($threads as $thread)
    $thread->join();

foreach ($store as $target => $data)
    printf("%s returned %d bytes\n", $target, strlen($data));
?>

当你到达这里时,你应该阅读我写的关于pthreads的每一个字,希望如此:)

您现在已经准备好看到一个更复杂但更相关的您正在进行的活动的示例,以下是为SO上的其他人编写的一些代码,它使用DOM / XPath从phpdocs获取文档描述。 ..

https://gist.github.com/krakjoe/b1526fcc828621e840cb

我认为应该有足够的代码和文档一天,对吧?

答案 1 :(得分:1)

您可以将线程输出附加到文件中。

我相信如果线程没有输出任何东西是因为它们不在与主脚本相同的上下文中运行。

编写文件或将其输出保存在某个数据库中,可以让您跟踪他们要说的内容。