2014-12-02 2 views
4

Возможно ли создать некоторый php-класс, который может запускать функции асинхронно? Вот то, что я сделал до сих пор:Выполнение функции async в php

class Worker extends Thread 
{ 
    protected $asyncFun; 
    protected $paramsArray; 

    public function run() { 
     $asyncFun(/*parameters go here*/) 
    } 

    public function setAsyncFunction($func, $paramsArr) 
    { 
     $this->asyncFun = $func; 
     $this->paramsArray = $paramsArr; 
    } 
} 

Вот как я хочу назвать его:

$worker = new Worker(); 
$worker->setAsyncFunction(foo, ["a", "b"]); 
$worker::start(); 
+0

Я бы породил новый php-скрипт с exec –

+0

@ Dagon вы можете разместить код? – vlio20

+0

'exec ('php script.php')' –

ответ

5

Последних версий поддержки Pthreads затворов в качестве членов, что делает код очень простой:

<?php 
class Background extends Thread { 

    public function __construct(callable $call, array $args = []) { 
     $this->call = $call; 
     $this->args = $args; 
    } 

    public function run() { 
     call_user_func_array($this->call, $this->args); 
    } 

    protected $call; 
    protected $args; 
} 

$background = new Background(function($greeting){ 
    printf("%s\n", $greeting); 
}, ["Hello World"]); 
$background->start(); 
$background->join(); 

function named($greeting) { 
    printf("%s\n", $greeting); 
} 

$background = new Background("named", ["Goodbye World"]); 
$background->start(); 
$background->join(); 
?> 

Однако, это ужасно, это трудно представьте себе любую функцию, которая так голодна, что для нее требуется нить. .

Вы начали вниз правильный путь с мыслью, что вы должны повторно использовать контекст и создать рабочий поток, Pthreads имеет все это построен в

Более разумный код с помощью встроенного в классах больше похоже:

<?php 
class Background extends Threaded { 

    public function __construct(callable $call, array $args = []) { 
     $this->call = $call; 
     $this->args = $args; 
    } 

    public function run() { 
     call_user_func_array($this->call, $this->args); 
    } 

    protected $call; 
    protected $args; 
} 

$pool = new Pool(4); 

$pool->submit(new Background(function($greeting){ 
    printf("%s\n", $greeting); 
}, ["Hello World"])); 

$pool->shutdown(); 
?> 

Но это все еще не имеет отношения к возвращаемому значению. Я предполагаю, что вы хотите получить результат вызовов, сделанных с помощью Pool, в этом случае код выглядит так:

<?php 
class Background extends Threaded { 

    public function __construct(callable $call, array $args = []) { 
     $this->call = $call; 
     $this->args = $args; 
    } 

    public function run() { 
     $this->synchronized(function(){ 
      $this->result = call_user_func_array 
       ($this->call, $this->args); 
      $this->notify(); 
     }); 
    } 

    public function getResult() { 
     return $this->synchronized(function(){ 
      while (!isset($this->result)) 
       $this->wait(); 
      return $this->result; 
     }); 
    } 

    protected $call; 
    protected $args; 
    protected $result; 
} 

$pool = new Pool(4); 

$call = new Background(function($greeting){ 
    return sprintf("%s\n", $greeting); 
}, ["Hello World"]); 

$pool->submit($call); 

echo $call->getResult(); 

$pool->shutdown(); 
?> 

Как вы можете видеть, вызов Background::getResult приведет в контексте вызова в ожидании пока результат не будет доступен, это может быть или не быть желательным, но является хорошим примером.

2

PHP является синхронным языком. Почти все, что вы сделаете, заставит PHP зависать, пока он заканчивается, и который включает в себя exec звонки, если вы хотите получить ответ.

Реализация, использующая основные элементы PHP, вероятно, потребует от вас выполнить exec или cURL-вызов, а затем просмотреть ваш сервер для вывода позже в вашем скрипте.

Вы можете использовать PECL, о котором упоминал Дагон (Gearman), но я лично считаю, что использование диспетчера очереди, такого как beanstalkd, намного проще в управлении.

Here - это сайт для beanstalkd. И here это хорошая PHP библиотеки для beanstalkd (с некоторыми примерами)

+0

Но почему? Есть класс Thread в php, почему бы не использовать его? – vlio20

+0

Нет встроенного многопоточного класса в установке PHP по умолчанию, о которой я знаю? Beanstalkd также имеет то преимущество, что не полагается на PHP и поддерживает несколько серверов. Вы могли бы иметь рабочих, которые занимают рабочие места в очереди в beanstalkd, которые написаны практически на любом языке. По сути, это быстрее и разнообразнее. – Scopey

+0

Как насчет этого: http://php.net/manual/en/class.thread.php – vlio20