简体   繁体   English

Laravel 命令、线程和闭包

[英]Laravel Commands, Pthreads and Closure

There is a need to perform a specific process multiple threads.需要多线程执行特定的进程。 I learned about the extension for php - pthreads.我了解了 php - pthreads 的扩展。

For example, a simple script outside Laravel works fine and I liked the results.例如,Laravel 之外的一个简单脚本运行良好,我喜欢结果。 I decided to move in Laravel, and faced with the problem.我决定搬到 Laravel,并面临这个问题。 Of course I searched in google, found some questions on stackoverflow, where replied the author of extension.当然我在谷歌搜索,在stackoverflow上发现了一些问题,在那里回答了扩展的作者。 But me did not help his answers, so I ask you to help me.但是我没有帮他回答,所以我请你帮帮我。

Answered Question extension author. 回答问题扩展作者。

There is a class App\\Commands\\QuestionsParserCommand.有一个类 App\\Commands\\QuestionsParserCommand。 Inside I created an instance of the class App\\My\\Questions\\QuestionsParser and call the method init().在里面,我创建了一个类 App\\My\\Questions\\QuestionsParser 的实例并调用方法 init()。 Then the code of the method 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();

Class ParserWorkers inherits from Worker and yet has an empty method run(). ParserWorkers 类继承自 Worker,但有一个空方法 run()。

As a result, I run the script and get a message in the log of php:结果,我运行脚本,在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

Information: Laravel 5.2.43, php 7.0.8, Windows信息:Laravel 5.2.43、php 7.0.8、Windows

Thank you all!谢谢大家!

First you can get acquainted with the strategy of the author of the library: https://github.com/krakjoe/pthreads-autoloading-composer首先可以熟悉一下库作者的策略: https : //github.com/krakjoe/pthreads-autoloading-composer

The strategy used here ensures that each thread (Worker) gets a thread local copy of the framework, or whatever is being loaded, but does not break the abilities of objects that descend from pthreads.此处使用的策略可确保每个线程(Worker)获得框架的线程本地副本或正在加载的任何内容,但不会破坏从 pthread 派生的对象的能力。


Secondly, to start working with laravel features (like Service Providers, Facades, Helpers, etc), you need to initialize laravel.其次,要开始使用 laravel 功能(如服务提供者、门面、助手等),您需要初始化 laravel。

I looked at how to initialize the application in the tests/CreatesApplication.php file.我查看了如何在 tests/CreatesApplication.php 文件中初始化应用程序。 The code below shows how to do this for Laravel 5.7 with php 7.2.下面的代码显示了如何使用 php 7.2 为 Laravel 5.7 执行此操作。

Important: specify the correct path to autoload.php and app.php relative to the Autoloader.php file location.重要提示:指定 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;
        }
    }

}

Now you can use Laravel with pthreads:现在您可以将 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM