douzhai7873
douzhai7873
2014-03-07 08:22
浏览 41
已采纳

PHP pthreads很奇怪

sorry for my twisted english - it is not my native.

I have a trouble: pthreads works, but in some strange way: for example, I cannot do "echo" from a thread.
Some example code from the internet:

<?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
");
        echo "Thread #{$this->index} finished
";
    }
    }
    $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";
?>

Script shows only "Done in: 0.14 seconds" (in webpage), no echoes, But! it is in error log:

$ 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" ...

In fact, I don't use any echo in my threads, I need to aggregate some webservices (each webservice class = thread), wait for the slowest thread, and merge all results to one array that could be taken from outside, but I never worked with threads in PHP or other languages before. I would appreciate if you give me some example. Thank you.

Software:
Gentoo x86
PHP 5.4.23 (nginx configured to use php-fpm)
Nginx 1.4.4

No apache. PHP built threadsafe, pthreads module is enabled.

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • douwei2966
    douwei2966 2014-03-07 09:19
    已采纳

    Standard output cannot be guaranteed, Zend provides no API to ensure you get the right stream, it cannot because of all the environments it works in, it is left to the software above PHP in your stack, FPM does count as above PHP in the stack, it does strange things with stderr/stdout - it has to in order to work at all.

    So, don't do that !

    As mentioned there's not really any need to write standard output anyway, if you want to log, then write a logger for files :)

    Here's your starting place:

    Read the articles in the Documentation section of that readme. The first explains exactly how pthreads manages to exist and how it works and will give you a good foundation of knowledge.

    The second describes the highest level of threading that we have right now, which is Pooling, you can skip that one ... I wouldn't :)

    Please do the reading, it will be of enormous help ...

    While you're reading and understanding, here is a semi-relevant example code listing which fetches pages from a few locations and stores the result in a shared array which the main thread can then process:

    <?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
    ", $target, strlen($data));
    ?>
    

    By the time you get to here, you should have read every word I have written about pthreads, hopefully :)

    You're now ready to see a more complex but more relevant example of the kind of activity you are undertaking, the following is some code written for someone else on SO, it uses DOM/XPath to fetch documentation descriptions from phpdocs ...

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

    I think that should be enough code and documentation for one day, right ??

    点赞 评论
  • doulang7699
    doulang7699 2014-03-07 08:27

    You could append your threads output into a file.

    I believe that if threads don't output anything is because they don't run in the same context than your main script.

    Writing files, or saving their output in some database will allow you to keep trace of what they have to say.

    点赞 评论

相关推荐