如何在 PHP7 中使用 pThreads 进行多线程?工人、游泳池等
How to multi-thread with pThreads in PHP7? workers, pool, etc
我目前想学习和实施pthreads - github。我已经用必要的组件编译了 php7
并验证了 thread-safety
已启用。我当前的示例代码有 4 个子 class 属于父 class Canine
。我应该如何相应地调用 Thread
class 以同时从下面显示的所有 classes 执行 bark()
?请记住当 classes 从 4 增长到 100 时的扩展能力。池?工作人员?
class Database {
private $_host;
private $_user;
private $_pass;
private $_dbname;
private $_dsn;
private $_options;
public static $pdo;
private $error;
private $stmt;
public function __construct() {
$this->_host = 'xxxxx';
$this->_user = 'xxxxx';
$this->_pass = 'xxxxx';
$this->_dbname = 'xxxxx';
$this->_dsn = 'mysql:host=' . $this->_host . ';dbname=' . $this->_dbname;
// Set options
$this->_options = array(
PDO::MYSQL_ATTR_LOCAL_INFILE => true,
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_TIMEOUT => 1,
);
}
public function __sleep() {
return array('_dsn', '_user', '_pass');
}
public function __wakeup() {
$this->connect();
}
public function connect() {
try {
return self::$pdo = new PDO($this->_dsn, $this->_user, $this->_pass, $this->_options);
} catch (PDOException $e) {
$this->error = $e->getMessage();
}
}
}
class DataAccessObject {
protected $database;
public function __construct() {
//Create Instance of DB
$this->database = (new Database())->connect();
}
public function insertQuery($query) {
try {
$select = $this->database->prepare($query);
$select->execute();
$results = $select->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
echo "Failed: " . $e->getMessage();
}
return true;
}
}
class Helper extends DataAccessObject {
//code elided
}
abstract class Canine extends Helper {
abstract public function bark();
}
//Child Classes
class GoldenRitriever extends Canine {
public function bark() { echo 'arf-arf!<br>'; }
}
class Pitbull extends Canine {
public function bark() { echo 'ruff-ruff!<br>'; }
}
class GermanShepherd extends Canine {
public function bark() { echo 'wao-wao!<br>'; }
}
class LabradorRetriever extends Canine {
public function bark() { echo 'woof-woof!<br>'; }
}
Creating instances and invoking `bark()`
$golden_ritriever = new GoldenRitriever();
$golden_ritriever->bark();
$pitbull = new Pitbull();
$pitbull->bark();
$german_shepherd = new GermanShepherd();
$german_shepherd->bark();
$labrador_retriever = new LabradorRetriever();
$labrador_retriever->bark();
我想你的问题出在解决方案的架构上,即你必须在某个地方扩展线程 class,但不确定在哪里。
假设 class 结构(Helper、DataAccessObject)是最终的,并且用 Thread 扩展 DataAccessObject 没有意义,我将按以下方式进行。
class ThreadedCanine extends Thread {
private $canine;
public function __construct(Canine $canine) {
$this->canine = $canine;
}
public function run() {
$this->canine->bark();
}
}
$threads = [
new ThreadedCanine(new GoldenRitriever()),
new ThreadedCanine(new Pitbull()),
new ThreadedCanine(new GermanShepherd()),
new ThreadedCanine(new LabradorRetriever()),
];
foreach($threads as $thread) {
$thread->start();
}
foreach($threads as $thread) {
$thread->join();
}
我认为这是一个好方法,因为它不会强制 Canine 成为线程,因为它可能不需要一直是线程。
编辑
我忘了在原来的回答中提到,如果你想扩展到 100 个线程,是的,你应该使用 Pool
和 Worker
class es 来管理它(文档甚至 recommend 使用 Worker 而不是 Thread),否则同时启动 100 个线程不会很好(如果你有多个客户端会变得更糟):P
一旦您更好地掌握了线程的使用,您就可以转向这些场景。
希望对您有所帮助:)
我目前想学习和实施pthreads - github。我已经用必要的组件编译了 php7
并验证了 thread-safety
已启用。我当前的示例代码有 4 个子 class 属于父 class Canine
。我应该如何相应地调用 Thread
class 以同时从下面显示的所有 classes 执行 bark()
?请记住当 classes 从 4 增长到 100 时的扩展能力。池?工作人员?
class Database {
private $_host;
private $_user;
private $_pass;
private $_dbname;
private $_dsn;
private $_options;
public static $pdo;
private $error;
private $stmt;
public function __construct() {
$this->_host = 'xxxxx';
$this->_user = 'xxxxx';
$this->_pass = 'xxxxx';
$this->_dbname = 'xxxxx';
$this->_dsn = 'mysql:host=' . $this->_host . ';dbname=' . $this->_dbname;
// Set options
$this->_options = array(
PDO::MYSQL_ATTR_LOCAL_INFILE => true,
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_TIMEOUT => 1,
);
}
public function __sleep() {
return array('_dsn', '_user', '_pass');
}
public function __wakeup() {
$this->connect();
}
public function connect() {
try {
return self::$pdo = new PDO($this->_dsn, $this->_user, $this->_pass, $this->_options);
} catch (PDOException $e) {
$this->error = $e->getMessage();
}
}
}
class DataAccessObject {
protected $database;
public function __construct() {
//Create Instance of DB
$this->database = (new Database())->connect();
}
public function insertQuery($query) {
try {
$select = $this->database->prepare($query);
$select->execute();
$results = $select->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
echo "Failed: " . $e->getMessage();
}
return true;
}
}
class Helper extends DataAccessObject {
//code elided
}
abstract class Canine extends Helper {
abstract public function bark();
}
//Child Classes
class GoldenRitriever extends Canine {
public function bark() { echo 'arf-arf!<br>'; }
}
class Pitbull extends Canine {
public function bark() { echo 'ruff-ruff!<br>'; }
}
class GermanShepherd extends Canine {
public function bark() { echo 'wao-wao!<br>'; }
}
class LabradorRetriever extends Canine {
public function bark() { echo 'woof-woof!<br>'; }
}
Creating instances and invoking `bark()`
$golden_ritriever = new GoldenRitriever();
$golden_ritriever->bark();
$pitbull = new Pitbull();
$pitbull->bark();
$german_shepherd = new GermanShepherd();
$german_shepherd->bark();
$labrador_retriever = new LabradorRetriever();
$labrador_retriever->bark();
我想你的问题出在解决方案的架构上,即你必须在某个地方扩展线程 class,但不确定在哪里。
假设 class 结构(Helper、DataAccessObject)是最终的,并且用 Thread 扩展 DataAccessObject 没有意义,我将按以下方式进行。
class ThreadedCanine extends Thread {
private $canine;
public function __construct(Canine $canine) {
$this->canine = $canine;
}
public function run() {
$this->canine->bark();
}
}
$threads = [
new ThreadedCanine(new GoldenRitriever()),
new ThreadedCanine(new Pitbull()),
new ThreadedCanine(new GermanShepherd()),
new ThreadedCanine(new LabradorRetriever()),
];
foreach($threads as $thread) {
$thread->start();
}
foreach($threads as $thread) {
$thread->join();
}
我认为这是一个好方法,因为它不会强制 Canine 成为线程,因为它可能不需要一直是线程。
编辑
我忘了在原来的回答中提到,如果你想扩展到 100 个线程,是的,你应该使用 Pool
和 Worker
class es 来管理它(文档甚至 recommend 使用 Worker 而不是 Thread),否则同时启动 100 个线程不会很好(如果你有多个客户端会变得更糟):P
一旦您更好地掌握了线程的使用,您就可以转向这些场景。
希望对您有所帮助:)