besanek/threads

PHP中的虚拟线程

dev-master 2014-05-13 11:16 UTC

This package is auto-updated.

Last update: 2024-09-10 21:29:09 UTC


README

##为什么?

  • 简单使用
  • 无需任何PHP扩展

安装

最佳安装方式是使用Composer

$ composer require besanek/threads:@dev

##使用方法

基本

很简单!

use Besanek\Threads;

// ...
$executable = new Threads\Executables\PhpExecutable('path/to/script.php');
$job = new Threads\Job($executable);
$job->run();

你可以编写自己的可执行程序,提供运行bash脚本、原生应用程序、内联PHP代码以及任何你想要的东西。只需实现Besanek\Threads\IExecutable接口。

让我们处理工作

有时我们需要读取输出,有时需要写入一些输入

$executable = new Threads\Executables\PhpExecutable('path/to/repeat.php');
$job = new Threads\Job($executable);
$job->run();
$job->write('Hello');
echo $job->read(); //Hello;

警告!子进程在另一个进程中运行,因此在读写时可能会有延迟。在这种情况下,不能保证read()返回'Hello'。如果子进程比当前脚本慢,就会发生这种情况。解决方案是等待循环,如下所示。

while(empty($output = $job->read())) {}

### It's OK or NOT?

How to react to end of the subscript? Callbacks!

```php
$ok = function () { echo "OK" };
$fail = function () { echo "FAIL" };
$job = new Threads\Job($executable, $ok, $fail);

两个回调都传递了3个参数。stdout、stderr和exitcode。

$ok = function ($stdout) { echo $stdout };
$fail = function ($stdout, $stderr, $exitcode) {
    echo "FAILS with exitcode: " . $exitcode . " and error: " . $stderr;
};

注意:回调在isDone()方法中处理,默认情况下在对象析构时调用。这可能太晚了。如果您需要更早地处理回调,请手动运行isDone()方法。理想情况下,在子进程仍在运行的情况下,在一个等待循环中。

while($job->isDone() === false) {}

### At the end is here management

Imagine, you need resize thousand of pictures. It's ideal for threads! But, if I creates thousand of subprocesses, I wastes all sources on my machine. Is there solution?

**Yes!** `Besanek\Threads\Runner`.

You can add set of jobs and limit the number of threads.

```php
$images = // do some black magic

$runner = new Threads\Runner(50); //Max 50 subprocess
foreach($images as $image) {
    $arguments = '-size=1000x1000 -output output/path/' . $image->name . '--source '.$image->path;
    $executable = new Threads\Executables\PhpExecutable('path/to/resize.php', $arguments);
    $job = new Threads\Job($executable);
    $runner->addJob($job);
    $runner->process();
}

信息:方法process()有一个参数,用于确定作业队列是否完全完成。因此,如果您调用process(true),整个队列将逐步运行,但会阻塞主进程,直到所有作业完成。默认情况下,在运行者的析构函数中调用。

警告!只有在process()方法中运行和完成作业。因此,如果您忘记调用它,作业将等待直到脚本结束。