PHP Pthreads不能将值传递给线程中的子对象


PHP Pthreads not able to pass values to child objects within the threads

所以,我有大约100+进程,我想让并行执行。我是用PHP的pthreads来做的。

我的问题是,线程启动,但他们不传递值给线程内初始化的另一个对象。我想做的是在单独的对象中执行每个子进程。

更新代码
<?php 
ini_set('display_errors', 1);
define('DEBUG', true);
function pr($var) {
   if (!DEBUG) {
       return;
   }
   echo PHP_EOL;
   if ($var) {
      print_r($var);
   } else {
      var_dump($var);
   }
   echo PHP_EOL;
}
class A {
   //public $results = 1;
   function init() {
      pr(__CLASS__ . ' initailized');
   }
   function getResult() {
       return ($this->results);
   }
}
class B extends A {
   public $val;
   public $results = [
       'queries' => []
   ];
   function set($k, $v) {
      $this->{$k} = $v;
   }
   function init() {
      pr(__CLASS__ . ' initailized');
      parent::init();
      $this->results = ['some_value' => true];
   }
}
class Fetching extends Thread {
    function __construct() {
    }
   public function run() {
      $this->e = new B;
      $this->e->init();
      pr($this->e->getResult());
   }
}
$data = [
   'id' => 12345,
   'message' => 'some text here'
];
$thread = new Fetching();
$thread->start();
$thread->join();
pr($thread);

当我运行$thread->结果时,它输出为NULL。但如果我把它设为字符串或整型就没问题了

我想这就是你的问题:

$threads[$i]->start(PTHREADS_INHERIT_NONE);

您可能需要PTHREADS_INHERIT_CLASSES才能访问ChildProcess类。


因为zend_heap错误(我不能重现它):你使用的是哪个版本的PHP和pthreads ?

我终于找到了答案。但我不太确定这是否是正确的行为。欢迎提出建议。

我正在做的是创建一个类变量$this->e并将其分配给子进程对象$this->e = new $object,然后运行init()方法。init方法返回一些查询作为类成员变量,即$this->e->queries将这些查询分配给它。我发现的修复是,我应该使用它作为线程对象的"运行"方法中的一个单独的变量。不作为类变量,一旦我有查询,我可以直接将其分配给类变量,并在做$thread->join()后调用它,如$thread->queries,它工作得很好。

简而言之-扩展到Thread的类的类变量不支持run方法中的对象。

下面是示例代码。我已经创建了两个文件。1. 包含所有对象和另一个处理器。php。见下文.

Objects.php包含以下代码:

<?php
class Controller {
   public $queries = [];
   public function init() {
   }
   public function set($key, $value) {
       $this->{$key} = $value;
       return $this;
   }
   function __destruct() {
       global $scriptStartTime;
       pr("Time taken for " . get_called_class() . " to execute = " .. executionTime($scriptStartTime, true));
   }
}
class SampleObject extends Controller {
  public function init() {
      parent::init();
      sleep(rand(0, 15));
      return $this->queries[] = 'INSERT INTO my_table (something) VALUES ("' . get_called_class() . '")';
  }
}
function pr($array) {
   echo PHP_EOL;
   print_r($array);
   echo PHP_EOL;
}
function executionTime($startTime, $text = false) {
   $time = @number_format(microtime(true) - $startTime, 3);
   $txt = 'seconds';
   if ($time > 60) {
      $time = @number_format($time / 60, 3);
      $txt = 'minutes';
   }
   if ($text) {
      $time = "{$time} {$txt}";
   }
   return $time;
}

Processor.php包含以下代码

ini_set('display_errors', 1);
require __DIR__ . DIRECTORY_SEPARATOR . 'Objects.php';
################ Processor #################
class Processor extends 'Thread {
    public function __construct($process) {
       $this->process = $process;
    }
    public function run() {
       //'Core'Autoloader::reload(); // reloading all autoloaders
       require __DIR__ . DIRECTORY_SEPARATOR . 'Objects.php';
       $scriptStartTime = microtime(true);
       # Dynamically creating objects for testing purpose.
       if (!class_exists($this->process['className'])) {
           eval("class " . $this->process['className'] . " extends SampleObject {}");
    }
       $object = (new $this->process['className']);
       # Set the default values that are common across all elements
       $object
            # Identity of thread
            ->set('name', $this->process['className'])
            # Options to carry the assigned values
            ->set('options', $this->process['options'])
            # The project details
            ->set('project', $this->project)
          ;
          $object->init();
          $this->queries = ($object->queries);
     }
}
$scriptStartTime = microtime(true);
for ($i = 0; $i < 150; $i++) {
  $jobs[] = [
      'className' => 'Object_' . $i,
      'options' => []
  ];
}
$totalJobsToExecute = count($jobs);
$i = 0;
# Initalizing threads
$threads = [];
$project = [
   'id' => 12345,
   'title' => 'Some cool stuff'
];
foreach ($jobs AS $process) {
   $i++;
   $proc = $process['className'];
   $threads[$proc] = new Processor($process);
   // In this sample code it works without PTHREADS_INHERIT_NONE, but with my code it doesn't    
   if ($threads[$proc]->start(PTHREADS_INHERIT_NONE)) {
      pr('Thread "' . $process['className'] . '" started');
   }
}
pr("Threads | Starting time = " . executionTime($scriptStartTime, true));
$queries = [];
foreach ($threads AS $thread) {
    if ($thread->join()) {
        $queries[] = $thread->queries;
    }
}
pr($queries);
pr('Count of threads === ' . count($threads));
pr("Threads time = " . executionTime($scriptStartTime, true));
pr("Threads | Total Threads executed = ({$i}) out of (" . $totalJobsToExecute . ")");