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

Joh*_*hnF 3 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);
}
Run Code Online (Sandbox Code Playgroud)

tpu*_*unt 6

在我看来,线程正确存储其数据的唯一方法是创建一个新的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
Run Code Online (Sandbox Code Playgroud)

这将输出:

Threaded Object
(
    [0] => 1
    [1] => 2
)
Run Code Online (Sandbox Code Playgroud)

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

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

很多开发人员在PHP中遇到线程问题时遇到的问题是,当他们Threaded从新线程内部创建对象时,然后希望能够在Threaded加入同一个线程时使用该对象.

例:

<?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)
Run Code Online (Sandbox Code Playgroud)

这将输出:

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

这是因为在加入生成的子线程时,Threaded对象in $thread->store已被破坏.这个问题也可能更加微妙.例如,在Threaded对象内创建新数组会自动将它们转换为Volatile对象(也是Threaded对象).

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

<?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);
Run Code Online (Sandbox Code Playgroud)

输出:

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

回到你的示例代码,你正在做的事情是绝对正常的,但只要你不尝试$this->someData在该子线程之外使用.