<?php declare(strict_types=1); ini_set('display_errors', 'On'); error_reporting(-1); // parallel\bootstrap()可以看作是子线程的require() parallel\bootstrap(__DIR__ . '/parallel.common.php'); // parallel\bootstrap()只能调用一次,否则会报如下错误: // PHP Fatal error: Uncaught parallel\Runtime\Error\Bootstrap: \parallel\bootstrap already set // parallel\bootstrap(__DIR__ . '/Human1.class.php'); // parallel\bootstrap(__DIR__ . '/Human2.class.php'); // 启动子线程(1) parallel\run(static function (string $name, string $gender, int $age): void { if (class_exists('Human1')) { echo 'Human1类存在' . PHP_EOL; $human1 = new Human1($name, $gender, $age); $human1->profile(); } else { echo 'Human1类不存在' . PHP_EOL; } global $counter; // $counter是parallel.common.php声明的变量,想在闭包函数里使用需要使用global修饰 $counter++; echo "子线程(1):\$counter = $counter" . PHP_EOL; }, ['张三', '男', 18]); // 休眠3秒钟再启动一个子线程 sleep(3); echo '……(休眠3秒后)……' . PHP_EOL; // 启动子线程(2) parallel\run(static function (string $name, string $gender, int $age): void { if (class_exists('Human2')) { echo 'Human2类存在' . PHP_EOL; $human2 = new Human2($name, $gender, $age); $human2->profile(); } else { echo 'Human2类不存在' . PHP_EOL; } global $counter; // $counter是parallel.common.php声明的变量,想在闭包函数里使用需要使用global修饰 $counter++; echo "子线程(2):\$counter = $counter" . PHP_EOL; }, ['李四', '女', 17]); //========== 控制台输出·开始 ==========// // Human1.class.php >> 若看到这句话则说明子线程已引入Human1类 // Human2.class.php >> 若看到这句话则说明子线程已引入Human2类 // parallel-bootstrap.php >> $counter的初始值为1024 // Human1类存在 // Human1::profile() ☛ 俺叫张三(男),今年18岁。 // 子线程(1):$counter = 1025 // ……(休眠3秒后)…… // Human2类存在 // Human2::profile() ☛ 俺叫李四(女),今年17岁。 // 子线程(2):$counter = 1026 //========== 控制台输出·结束 ==========// //========== 总结 ==========// // 1、子线程和主线程是代码隔离的,主线程里定义的类无法在子线程里使用,而parallel\bootstrap()可以看作是子线程的require_once(),通过该 // 方法可以在子线程里引入开发者自己的类库和函数库,从而在子线程里使用。 // 2、parallel\bootstrap()在主线程里只能调用一次,所以应该写一个common文件让其引入,然后在common文件里再引入开发者自己的类库和函数库。 // 3、parallel\bootstrap()引入的内容是所有子线程共享的,其中也包括普通变量,但是要注意的是这些变量需要使用global修饰才能在闭包函数里 // 使用。由于子线程是并发执行存在资源竞争问题,所以对于引入的变量应该只读不写,想在子线程之间传递数据必须使用管道或Redis等工具。 // 4、parallel\bootstrap()并不是调用时就立即执行参数指定的PHP脚本,而是有子线程启动才会执行,如果一直没有子线程启动那么就会一直等待。 // 并且由于子线程是并发执行,可能会出现两次执行脚本的问题,例如上面把休眠3秒注释掉就会出现两次执行parallel.common.php的情况,但这 // 并不会导致程序报错。
<?php // parallel.common.php declare(strict_types=1); ini_set('display_errors', 'On'); error_reporting(-1); // 引入开发者自己的类库 require_once __DIR__ . '/Human1.class.php'; require_once __DIR__ . '/Human2.class.php'; // 引入开发者自己的函数库 require_once __DIR__ . '/function.lib.php'; $counter = 1024; echo "parallel-bootstrap.php >> \$counter的初始值为1024" . PHP_EOL;
<?php // Human1.class.php declare(strict_types=1); ini_set('display_errors', 'On'); error_reporting(-1); /** * Human1类 */ class Human1 { private string $name; private string $gender; private int $age; public function __construct(string $name, string $gender, int $age) { $this->name = $name; $this->gender = $gender; $this->age = $age; } public function profile(): void { echo "Human1::profile() ☛ 俺叫{$this->name}({$this->gender}),今年{$this->age}岁。" . PHP_EOL; } } echo 'Human1.class.php >> 若看到这句话则说明子线程已引入Human1类' . PHP_EOL;
<?php // Human2.class.php declare(strict_types=1); ini_set('display_errors', 'On'); error_reporting(-1); /** * Human2类 */ class Human2 { private string $name; private string $gender; private int $age; public function __construct(string $name, string $gender, int $age) { $this->name = $name; $this->gender = $gender; $this->age = $age; } public function profile(): void { echo "Human2::profile() ☛ 俺叫{$this->name}({$this->gender}),今年{$this->age}岁。" . PHP_EOL; } } echo 'Human2.class.php >> 若看到这句话则说明子线程已引入Human2类' . PHP_EOL;
Copyright © 2024 码农人生. All Rights Reserved