[英]Laravel Commands, Pthreads and Closure
需要多線程執行特定的進程。 我了解了 php - pthreads 的擴展。
例如,Laravel 之外的一個簡單腳本運行良好,我喜歡結果。 我決定搬到 Laravel,並面臨這個問題。 當然我在谷歌搜索,在stackoverflow上發現了一些問題,在那里回答了擴展的作者。 但是我沒有幫他回答,所以我請你幫幫我。
回答問題擴展作者。
有一個類 App\\Commands\\QuestionsParserCommand。 在里面,我創建了一個類 App\\My\\Questions\\QuestionsParser 的實例並調用方法 init()。 然后方法init()的代碼:
// Create a pool
$pool = new Pool($this->threads, ParserWorkers::class);
// Create a thread class
$thread = new class extends Threaded
{
public function run()
{
// The class will receive data from a provider
// that will be shared between threads through ParserWorkers.
// It will work with the API and store the data in the database.
// The need to work with the threads,
// because the data for processing an incredible amount.
echo '+';
}
};
// Start a threads
for ($i = 0; $i < $this->threads; $i++) {
$pool->submit($thread);
}
$pool->shutdown();
ParserWorkers 類繼承自 Worker,但有一個空方法 run()。
結果,我運行腳本,在php的日志中得到一條消息:
[13-Oct-2016 11:27:35 Europe/Moscow] PHP Fatal error: Uncaught Exception: Serialization of 'Closure' is not allowed in [no active file]:0
Stack trace:
#0 {main}
thrown in [no active file] on line 0
信息:Laravel 5.2.43、php 7.0.8、Windows
謝謝大家!
首先可以熟悉一下庫作者的策略: https : //github.com/krakjoe/pthreads-autoloading-composer
此處使用的策略可確保每個線程(Worker)獲得框架的線程本地副本或正在加載的任何內容,但不會破壞從 pthread 派生的對象的能力。
其次,要開始使用 laravel 功能(如服務提供者、門面、助手等),您需要初始化 laravel。
我查看了如何在 tests/CreatesApplication.php 文件中初始化應用程序。 下面的代碼顯示了如何使用 php 7.2 為 Laravel 5.7 執行此操作。
重要提示:指定 autoload.php 和 app.php 相對於 Autoloader.php 文件位置的正確路徑。
namespace App\Console\Commands;
use Worker;
use Illuminate\Contracts\Console\Kernel;
class Autoloader extends Worker
{
public function run()
{
require __DIR__. '/../../../vendor/autoload.php';
$app = require __DIR__.'/../../../bootstrap/app.php';
$app->make(Kernel::class)->bootstrap();
}
public function start($options = PTHREADS_INHERIT_ALL)
{
return parent::start(PTHREADS_INHERIT_INI);
}
}
namespace App\Console\Commands;
use Exception;
use Threaded;
class OperatorThread extends Threaded
{
/**
* @var OperatorThreaded
*/
private $operator;
private $error;
public function __construct(OperatorThreaded $operator)
{
$this->operator = $operator;
}
public function run()
{
try {
$this->operator->handle();
} catch (Exception $exception) {
$this->error = (string) $exception;
}
}
public function getError() {
return $this->error;
}
}
namespace App\Console\Commands;
class OperatorThreaded
{
private $i;
public function __construct($i)
{
$this->i = $i;
}
public function handle()
{
sleep(rand(1,3));
if (app()->isBooted()) {
echo $this->i . PHP_EOL;
}
}
}
現在您可以將 Laravel 與 pthreads 一起使用:
namespace App\Console\Commands;
use Pool;
use Illuminate\Console\Command;
class Test extends Command
{
protected $description = 'test';
protected $signature = 'test';
public function handle()
{
$operators = [];
for ($i=0; $i<5; $i++) {
$operators[] = new OperatorThreaded($i);
}
$pool = new Pool(count($operators), Autoloader::class);
foreach ($operators as $operator) {
$thread = new OperatorThread($operator);
$pool->submit($thread);
}
while ($pool->collect());
$pool->shutdown();
}
}
$ php artisan test
1
2
4
0
3
foreach ($this->pool as $w) {
$w->start(PTHREADS_INHERIT_ALL ^ PTHREADS_INHERIT_CLASSES);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.