PHP线程应如何存储其数据?

时间:2017-06-26 22:18:56

标签: php multithreading pthreads php-7.1

所以我一直在谷歌搜索和阅读有关PHP pthreads3以及它们应该如何存储数据的互联网。 (或者更确切地说,他们不是这样) 在我看来,线程正确存储其数据的唯一方法是创建一个新的Threaded对象并将其发送到线程。然后,线程可以使用此Threaded对象来存储几乎所有数据。

我的问题,以及掌握PHP线程的最大问题: 是否可以让线程在需要时创建自己的存储对象? 我不知道怎么或为什么,因为我在这上面找到的所有答案都说明了一个含糊不清,精心设计和令人困惑的问题,但可能,但没有",主要与性能差和内存问题/安全性有关。 这看起来应该是可能的,不知何故:

class someFantasticThread extends Thread {
    public $someData;

    function run(){
        while(true){
            //Create a fresh storage for the new data this iteration
            $this->someData = new SomeCoolStorage(); // Can this work somehow without all the issues?
            $this->someData[] = 'amazingdata'; // Do something amazing and store the new results in $someData
            $this->someData[] = new SomeCoolStorage(); // This would also be desireable, if it can somehow be done
            //don't mind the obvious loop issues. Imagine this is a well formed loop
        }
    }
}

class SomeCoolStorage extends Threaded{}

// Start the thread
$threadObj = new someFantasticThread();
$threadObj->start();
while(true){
    // at some point, retrieve the data and do something useful with the contained results
    // doSomethingAwesome($threadObj->someData);
}

2 个答案:

答案 0 :(得分:5)

  

在我看来,线程正确存储数据的唯一方法是创建一个新的Threaded对象并将其发送给线程。

是的,这是一种方法。

  

是否可以让线程在需要时创建自己的存储对象?

是的,但前提是你在该线程内操作它(或者它可能产生的任何子线程)。

在PHP中使用线程时要理解的基本事项之一是Threaded的对象与创建它们的上下文相关联。这意味着如果在主线程中创建Threaded对象,将此对象传递给生成的子线程,然后加入该生成的子线程,则可以继续正常使用该Threaded对象

示例1(构造函数注入):

<?php

$store = new Threaded(); // created in the main thread

$thread = new class($store) extends Thread {
    public $store;

    public function __construct(Threaded $store)
    {
        $this->store = $store;
    }

    public function run()
    {
        $this->store[] = 1;
        $this->store[] = 2;
    }
};

$thread->start() && $thread->join();

print_r($store); // continue using it in the main thread

这将输出:

Threaded Object
(
    [0] => 1
    [1] => 2
)

在上面的示例中,我们还可以在构造函数内部创建Threaded对象,然后在脚本末尾执行var_dump($thread->store);。这是因为Threaded对象仍然在需要它的最外层范围内创建,因此它不依赖于可能已经被销毁的任何子线程的范围。 (PHP中Thread在单独线程中执行的唯一部分是Thread::run方法。)

与上面的例子类似,我们也可以使用setter注入。 (但是,只要在最外层范围内使用Threaded对象的线程调用setter,就可以了。)

许多开发人员在PHP中遇到新线程的问题似乎是他们从新线程内部创建Threaded对象,然后期望能够使用{{1}对象,当他们加入同一个线程时。

示例:

Threaded

这将输出:

  

RuntimeException:pthreads检测到尝试连接到已在%s中销毁的对象:%d

这是因为加入生成的子线程时<?php $thread = new class() extends Thread { public $store; public function run() { $this->store = new Threaded(); // created inside of the child thread $this->store[] = 1; $this->store[] = 2; } }; $thread->start() && $thread->join(); print_r($thread->store); // attempt to use it in the outer context (the main thread) 中的Threaded对象已被破坏。这个问题也可能更加微妙。例如,在$thread->store个对象内创建新数组会自动将它们转换为Threaded个对象(也是Volatile个对象)。

这意味着以下示例也不起作用:

Threaded

输出:

  

RuntimeException:pthreads检测到尝试连接到已在%s中销毁的对象:%d

要回到您的示例代码,您正在做的事情绝对没问题,但只要您不尝试在该子线程之外使用<?php $thread = new class() extends Thread { public $store; public function run() { $this->store = []; $this->store[] = 1; $this->store[] = 2; } }; $thread->start() && $thread->join(); print_r($thread->store);

答案 1 :(得分:-2)

不要使用PHP线程。它们基本上没用,这就是原因:

首先:Threads can only be used in the PHP CLI,用于独立的命令行脚本。它们不能在PHP Web应用程序中使用。在Web应用程序中,通过允许一次运行多个请求来获得并发性。 (这在Web服务器环境中自然发生。)

第二:使用线程需要在应用程序的所有部分中提供广泛的显式支持。不扩展Threaded的类不能在线程应用程序中使用 - 这使得大多数PHP类和框架不可用。事实上,即使是一些内置的PHP类也无法在线程代码中安全使用。

问题的长短是:PHP pthreads扩展是一种半心半意的尝试,将线程引入一种从未设计为支持它的语言。扩展非常有限,使用起来不方便,而且速度慢。避免它。