Пользователь
0,0
рейтинг
18 сентября 2008 в 19:47

Разработка → Эмуляция многопоточности в PHP

PHP*
Суть многопоточности (для приложения) состоит в том, что процесс может состоять из нескольких (однотипных) потоков, выполняющихся «параллельно», то есть без упорядочивания по времени — выполнился один, пошел следующий. Использование многопоточности позволяет ускорить выполнение задачи и/или снизить нагрузку, таким образом, улучшая быстродействие самого приложения.

PHP относится к языкам, в которых поддержка многопоточности отсутствует. Но, есть немало задач, в которых она была бы очень полезна. Как правило, это задачи, в которых одно действие нужно выполнить много раз, но с различными параметрами, причем само действие настолько ресурсоемко, а количество итераций настолько велико, что обычный цикл использовать невозможно.

Я рассмотрю простой пример, как можно достичь эмуляции многопоточности в PHP.

Допустим, нам нужно осуществить почтовую рассылку на очень большое количество адресов. Адреса хранятся в базе. Так как адресов много, то такой вариант нам не подходит, повесим сервер:

$res mysql_query('SELECT `email` FROM `user`');

while (
$row mysql_fetch_assoc($res))
    
mail($row['email'], $theme$text);


Если мы хотим использовать для этой задачи многопоточность, то неплохо бы выглядел следующий вариант:

$res mysql_query('SELECT `email` FROM `user`');

$data = array();

while (
$row mysql_fetch_assoc($res))
    
$data[] = $row;
    
$multithreading = new MultiThreading();

// mailer.php — скрипт, который отправляет письмо по адресу, переданному ему методом GET,
// то есть mailer.php?email=somebody@example.com
$multithreading->setScriptName('mailer.php');

$multithreading->setParams($data);

$multithreading->execute();


Все просто и удобно. Осталось написать соответствующий класс, что я и сделал. Вот он, со всеми пояснениями в комментариях.

class MultiThreading
{
    
/**
     * Имя сервера
     *
     * @var string
     * @access private
     */
    
private $server;
    
    
/**
     * Максимальное количество потоков
     *
     * @var int
     * @access private
     */
    
private $maxthreads;
    
    
/**
     * Имя скрипта, который выполняет нужную нам задачу
     *
     * @var string
     * @access private
     */
    
private $scriptname;
    
    
/**
     * Параметры, которые мы будем передавать скрипту
     *
     * @var array
     * @access private
     */
    
private $params = array();
    
    
/**
     * Массив, в котором хранятся потоки
     *
     * @var array
     * @access private
     */
    
private $threads = array();
    
    
/**
     * Массив, в котором хранятся результаты
     *
     * @var array
     * @access private
     */
    
private $results = array();
    
    
/**
     * Конструктор класса. В нем мы указываем максимальное количество потоков и имя сервера. Оба аргумента необязательны.
     *
     * @param int $maxthreads максимальное количество потоков, по умолчанию 10
     * @param string $server имя сервера, по умолчанию имя сервера, на котором запущено приложение
     * @access public
     */
    
public function __construct($maxthreads 10$server '')
    {
        if (
$server)
            
$this->server $server;
        else
            
$this->server $_SERVER['SERVER_NAME'];
        
        
$this->maxthreads $maxthreads;
    }
    
    
/**
     * Указываем имя скрипта, который выполняет нужную нам задачу
     *
     * @param string $scriptname имя скрипта, включая путь к нему
     * @access public
     */
    
public function setScriptName($scriptname)
    {
        if (!
$fp fopen('http://'.$this->server.'/'.$scriptname'r'))
            throw new 
Exception('Cant open script file');
        
        
fclose($fp);
        
        
$this->scriptname $scriptname;
    }
    
    
/**
     * Задаем параметры, которые мы будем передавать скрипту
     *
     * @param array $params массив параметров
     * @access public
     */
    
public function setParams($params = array())
    {
        
$this->params $params;
    }
    
    
/**
     * Выполняем задачу, комментарии в коде
     *
     * @access public
     */
    
public function execute()
    {
        
// Запускаем механизм, и он работает, пока не выполнятся все потоки
        
do {
            
// Если не превысили лимит потоков
            
if (count($this->threads) < $maxthreads) {
                
// Если удается получить следующий набор параметров
                
if ($item current($this->params)) {
                
                    
// Формируем запрос методом GET
                    
                    
$query_string '';
                
                    foreach (
$item as $key=>$value)
                        
$query_string .= '&'.urlencode($key).'='.urlencode($value);
                    
                    
$query "GET http://".$this->server."/".$this->scriptname."?".$query_string." HTTP/1.0\r\n";
                    
                    
// Открыватем соединение
                    
                    
if (!$fsock fsockopen($this->server80))
                        throw new 
Exception('Cant open socket connection');
                
                    
fputs($fsock$query);
                    
fputs($fsock"Host: $server\r\n");
                    
fputs($fsock"\r\n");
                
                    
stream_set_blocking($fsockO);
                    
stream_set_timeout($fsock3600);
                    
                    
// Записываем поток
                
                    
$this->threads[] = $fsock;
                    
                    
// Переходим к следующему элементу
                
                    
next($this->params);
                }
            }
            
            
// Перебираем потоки
            
foreach ($this->threads as $key=>$value) {
                
// Если поток отработал, закрываем и удаляем
                
if (feof($value)) {
                    
fclose($value);
                    unset(
$this->threads[$key]);
                } else {
                    
// Иначе считываем результаты
                    
$this->results[] = fgets($value);
                }
            }
            
            
// Можно поставить задержку, чтобы не повесить сервер
            
sleep(1);
            
        
// ... пока не выполнятся все потоки    
        
} while (count($this->threads) > O);
    
        return 
$this->results;
    }
}



Также можно этот класс скачать, чтобы не копипастить :-).

UPD: господа, хочу напомнить, все же это скорее развернутый пример, нежели идеальное готовое решение.

P.S. Парсер почему-то сьедает конструкции типа «$var > 0», поэтому в двух местах (stream_set_blocking($fsock, 0); и while (count($this->threads) > 0);) я заменил цифру 0 на букву O. В классе для скачивания все нормально.

Оригинал статьи.
Андрей Сабинин @s_a_p
карма
48,6
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (76)

  • –3
    Хе-хе, неплохая нагрузочка на сервер получится, как бы он не сломался, был у нас один коллега, который крон запускал в несколько потоков, дергая страницы через http… это печально было…
    • 0
      Все зависит от поставленной задачи. Кроме того, мне было интересно реализовать эту вещь.
    • +1
      На то и есть настройки — выставлять количество потоков нужно соответственно возможностям сервака и канала.
      • 0
        Да хоть какие настройки, дергание с сервера своих же страниц через http считаю бредовой идеей, особенно для тяжелых задач. лучше уж внутри запустить все те же скрипты, не задрачивая апачку.
        • +1
          Не соглашусь с вами, все спамилки php-ые (ну год назад точно все, может за парой исключений) работали таким вот образом и как-то не грузили апач. Откуда знаю? Смотрел внутренности сам.
          • 0
            ну и микроскопом можно гвозди забивать, кстати, так можно забивать, чтоб микроскоп не испортился. ;)
            • 0
              Эта шутка заезженная. Я вам говорю как есть и в данном случаи это было оправдано — один раз при старте основной скрипт дергал n раз с параметрами другой скрипт.
              • 0
                Я понял о чем вы и что имеете в виду. Но говорю о том, что это далеко не бест практикс ;)
  • +6
    Идея интересная, но я бы её описал словами, что бы можно было оценить, нечитая код. Выступая в качестве капитана очевидности, разъясняю: автор использовал многопоточность вебсервера и неблокирующие операции для работы с сокетами.

    Я PHP не знаю, разве нельзя было бы достигнуть того же эффекта, используя что-то типа exec для запуска php скрипта как процесса OS и неблокирующие операции для работы с ним?
    • 0
      Спасибо за объяснение :) А я подумал, что комментариев в коде будет достаточно.

      Я PHP не знаю, разве нельзя было бы достигнуть того же эффекта, используя что-то типа exec для запуска php скрипта как процесса OS и неблокирующие операции для работы с ним?

      Мне была интересна именно программная реализация, возможно, даже с теоретической точки зрения :)
    • +1
      можно. Но обработка нескольких потоков в одном скрипте, чем для каждого потока по скрипту, займет меньше ресурсов (память, процессорное время на запуск и остановку процесса)
  • +7
    • 0
      Спасибо, интересный материал.
    • НЛО прилетело и опубликовало эту надпись здесь
  • +8
    В данном случае через HTTP жутко глупая идея, т.к.
    1). Займёт WEB сервер работой, что плохо. Может получиться ситуация, когда пользователи будут ждать, пока их запрос обработается WEB сервером.
    2). Время коннекта по HTTP даже локально довольно большое. В крайнем случае лучше уж Unix socket или pipes.

    Делать такие вещи нужно скриптами, работающими в командной строке. Т.к.
    1). Можно установить приоритет исполнения (proc_open)
    2). Не ограничены ресурсы и время исполнения (злоупотреблять конечно этим не нужно).

    Я думаю вам стоит изучить вот этот раздел мануала: lv.php.net/manual/ru/refs.fileprocess.process.php
  • 0
    Суть многопоточности в shared state, что на php реализовать невозможно, да и не потоки это, а отдельные системные процессы. В общем, надо не страдать фигнёй, а взять нормальный тул с поддержкой многопоточности типа Java, если это действительно так надо.
    • +1
      Суть многопоточности в shared state, что на php реализовать невозможно, да и не потоки это, а отдельные системные процессы.

      Потому и эмуляция.
      • –1
        Эмуляция обычно подразумевает собой наличие полного функционала, пусть и с определёнными trade-offs.
    • 0
      По мимо Java, есть ещё масса других языков… Не Java'ой едины!
      • 0
        Масса? Может назовёте другие активно применяющиеся языки для concurrent programming? Ну C#… Есть ещё Erlang/Scala с Actor Model, которая скорее всего заменит SM-модель. Вот вообщем то и всё.
        • 0
          ДА, масса! Я могу назвать только те, которые мне ближе — C++, Delphi.
          А, вот, ваше выражение concurrent programming — это не показатель. Каждый язык имеет право на существование и разрабатывался для определённых целей!

          И не розжигайте холивар про concurrent programming
          • 0
            Delphi — это не язык программирования. Это IDE
        • 0
          Python/Stackless?
  • +5
    Слишком громкий заголовок, но, увы, выбрана не слишком подходящая терминология.

    Собственно это вряд ли эмуляция и PHP здесь совсем не причём. Подобные запросы к серверу выполняющему задачи параллельно можно генерировать любым удобным способом (то есть PHP можно смело удалить из заголовка). Затем, многопоточность — это несколько иное понятие, относящееся к множеству «потоков исполнения» в контексте одного процесса (характерный признак — разделяемые ресурсы, доступные потокам в рамках процесса).

    Можно было использовать асинхронные (неблокирующие) сокеты PHP (реализовав протокол SMTP средствами PHP), это можно было бы назвать «эмуляцией» многопоточности (понадобился бы «планировщик» обслуживающий события на сокетах).

    Статья скорее об организации многозадачности посредством подходящего web-сервера, нежли о многопоточности в PHP. Да собственно, можно было воспользоваться средствами ОС используя какое-нибудь приложение для отправки почти (например запуская через exec() программу sendmail), что уменьшило бы накладные расходы.
    • 0
      Вызывать sendmail & через exec нельзя, так как тогда не получится контролировать количество процессов. Например, что будет, если нужно отправить десятки тысяч E-mails? Тут вообще сам подход неверный для данного класса задач.
      • 0
        Соглашусь, exec() не подходит в данном случае. Больше подходи proc_open() и аналоги. Мысль была, что прослойка в виде web-сервера излишня (конкретика реализации альтернативы не представлялась для меня важной во время написания).
        • 0
          не соглашусь… где ваши мозги?! будьте гибче!
          пишите куда-то, что стартанул… читайте откуда-то процессы… всё просто!

          Мозги нужно ставить в режим ВКЛ.!
  • +2
    1. Как будет вести себя система, если основной скрипт прервет работу, обработав лишь половину данных?

    2. Веб сервер может не взять запрос на обслуживание, если перегружен. Тогда что, получится, что скрипт не выполнит обработку всех данных?

    3. Что будет, если основной скрипт будет запущен не один раз, а нечаянно несколько раз подряд?

    4. Не кажется ли Вам, что, если нужно обработать большой объем данных (скажем, в Вашем примере, отправив десяток тысяч E-mails), основной скрипт, который использует Ваш класс, может умереть например по таймауту?

    В общем можно еще долго рассказывать… но в двух словах — пожалуйста, никогда-никогда не делайте так.
    • –2
      1. В зависимости от того, как вы его будете использовать.
      2. Если сервер не берет запрос на обслуживание, потому что перегружен, это плохо в любом случае, а не только в этом.
      3. Зависит от задачи. Если у вас не стоит проверка, то действия выполнятся несколько раз.
      4. Можно увеличить max_execution_time

      Вобщем, это все же это скорее развернутый пример, нежели идеальное готовое решение.
  • 0
    Как так нет многопоточности? Есть форки.
    • +4
      Форк — это процесс. К многопоточности он имеет такое же отношение, как банан к попугаю.
      • 0
        PHP не многопоточный язык. Мы не говорим о многопоточности, говорим о её эмуляции.
        А форк имеет к этому самое прямое отношение. К эмуляции многопоточности.
        Посредством форка можно достичь этой эмуляции, если постараться.
        • 0
          Нельзя. Эмуляция — это полная реализация через костыли.
          Если хочешь оспорить, то пожалуйста напиши мне, как работать с общими переменными в разных потоках.
          Иначе реализация будет не полной.
          • +1
            Запросто. Через memcached например. Чтоб значение переменной было в разделяемой памяти.
            • 0
              Как переменная узнает, что «она» изменилась в другом «потоке», чтобы получить новое значение через memcached?
              Как ты предлагаешь сделать это автообновление значения?
              Как будут реализованы критические секции?
          • –1
            Либо memcached, либо pipe
            Сообщать др. процессу о том что были изменения можно через сигналы
            • 0
              Чё-то у вас мешанина какая-то. Вы про race conditions слышали? В случае shared state(пусть в memcached) — надо лочить ресурсы, а не сигналы посылать.
              • 0
                Это ошибки проектирования.
                • 0
                  ппц … Ваш подход к работе с общими ресурсами тогда какой?

                  Процессы A & B
                  Ресурс C в memcached

                  Как вы собираетесь разруливать запросы A и B к C сигналами?
                  • 0
                    Встряну боком.
                    Scala, не кипятись, race conditions для веба (в основном) — это как магнит для диэлектрика. При желании разрулить можно, memcached тут ни при чем. Грамотный человек знает про shmem, семафоры и сигналы. И прекрасно себе понимает что никаких потоков, но почти чистый IPC.
          • 0
            Повесьте демона на PHP и торчите сколько хотите :)
            Демон хранит необходимые данные у себя. При необходимости — из каждого процесса можно получить значение.
  • +1
    Давайте я тоже поделюсь своими мыслями о том, как делался многопоточность на PHP.

    1. Ну, во-первых в PHP есть специальный (правда, не совсем надежный) механизм для этого: называется Process Control, который работает только на основе никсов. ru2.php.net/manual/ru/book.pcntl.php
    Я редко видел, чтоб подобное использовалось, вероятно потому что данное решение просто невозможно нормально отлаживать (я пытался, ага).

    2. С помощью запусков php-скриптов из php командами System program execution — ru2.php.net/manual/ru/book.exec.php. Суть такая запускаем фоновое выполнение скрипта и работаем дальше, а он там в фоне вытворяет уже сто-то своё. Единственное — такими скриптами сложно управлять. Для этого я делал так — создавал таблицу, и каждый новый запущеный скрипт вносил в неё новую строчку. Автоинкремент получался уникальным идентификатором процесса. Скрипт крутился в бесконечном цикле и опрашивал таблицу на предмет существования своей строчки, и если её не находил — то завершался. Ну, или просто — выполнял то, что нужно и опять же — завершался. Кстати, на такой подход замечательно смтрится для рассылки — мы добавляем адреса в некую базу, а скрипт висит себе запущеным, извлекает из неё записи и рассылает по ним. Да, не все сразу. За то надежно. :-) Я сделал вывод — самый надежный способ.

    3. Использование http. Это очень спорно, лучше этого не делать — потому что ответа все равно придется ждать. И хоть используй curl_multi_exec, хоть еще что-то — не. Это и сервер вводин в нагрузку и вообще как-то… Кстати, чтоб обойти это ожидание я пытался сделать следующее «гениальное» решение. Открывал поток к скрипту он какбэ начинал выполнятся, а я раз — и тупо закрывал соединение. Один раз это сработает нормально. Даже два. До тех пор, пока на сервер на ляжет нагрузка, тогда апач начнет рубить такие безисходные процессы. Вобщем, не работает это. И вообще хак. :-))

    4. Да, еще можно сделать подобие daemon-а на php — язык это позволяет. Это понадежнее и устойчевее, чем HTTP, но сложнее.

    Самый надежный способ все же — это нормально организованный механизм запуска фонового скрипта. С вычислением и присвоением ID, проверкой мертвых и зависших скриптов, обмена через базу, Memcached или семафоры.
    • 0
      У меня как раз работает демон на php, довольно стабильно, несколько месяцев без перезапуска.
      На сокетах.
      Но все таки как то сомнительно это все, для прототипа терпимо, но для продакшн писать демонов на пхп не хочется.
      • 0
        А у меня уже не один месяц в продакшене крутится демон написанный и использованием pcntl и ipc. Работает себе, принимает соединения как многопоточный сокет-сервер и замечательно обрабатывает полученные данные. Нагрузка на аппаратную часть в холостом режиме — просто смешная, в рабочем — терпимая. Основная часть ее падает не на php, а на обработку данных в СУБД — объемы просто очень большие.
  • 0
    делал похожую задачу — shell оболочку под винду писал для себя. через пайпы (pipe_open). пришлось стандартизировать обмен информацией. коряво, но работало (код утерян со сносом винды)
  • НЛО прилетело и опубликовало эту надпись здесь
    • НЛО прилетело и опубликовало эту надпись здесь
      • +2
        Для настойчивых объясню. Статья была размещена в блоге PHP и в статье (пусть и не слишком хорошо, на мой взгляд) раскрывается тема реализации задачи средствами именно этого языка. Если хочется обсуждать шарп — вы замечательно можете сделать это вместе с вашими единомышленниками в соответствующем блоге.
        • НЛО прилетело и опубликовало эту надпись здесь
          • 0
            А холивар значит умно? У каждого разработчика свои причины выбирать тот или иной язык для использования его в разработке. Вам, как и мне, для каждого отдельного случая, они не ведомы, а значит и не наше дело навязывать(!) язык для реализации.
            • НЛО прилетело и опубликовало эту надпись здесь
              • 0
                А я к слову статью и не хвалил.
                • НЛО прилетело и опубликовало эту надпись здесь
            • –1
              А мне кажется что есть языки подходящие для задач и не подходящие.
              Темы новых постов: Операционная система на ПХП!, звучит? но смысл?

              З.Ы. Не видел в комменте phpdude навязывания. Он просто прав. Кесарю кесарево, а слесарю…
              • 0
                Простите, конечно, не в ваш конкретно адрес будет сказано, но у меня складывается стойкое убеждение, что ярые противники PHP с ним знакомы исключительно по книгам «освой за 24 часа».
                Что значит подходящие и не подходящие? Есть в PHP средства для управления процессами и их взаимодействия, значит предназначен. А то что написанное приложение может быть несколько более ресурсоемким чем на Сях — так это уже нюансы. Перл вот например лучше чем С справляется с обработкой больших массивов текстовой информации, но это же не повод писать на перле ВСЁ приложение, которое вынуждено лишь малую долю времени работать с текстом. Так же и управление процессами может быть лишь малой толикой того, чем будет заниматься приложение написанное на PHP.
                Выбирать язык для реализации может лишь разработчик в полной мере представляя, чем его будущее детище должно заниматься. И отказываться от языка только потому, что какую-то часть задач он выполняет несколько хуже чем другие (но, заметьте, выполняет) я думаю не стоит. Именно об этом я писал в посте выше.

                P.S.: и здесь я еще не затрагивал вопросы командной работы над проектом, стоимости и сроков разработки, и многих других факторов влияющих на процесс девелопмента.
                • 0
                  > Перл вот например лучше чем С справляется с обработкой больших массивов текстовой информации

                  Ооочень напоминает бред Жабистов о том, что Java работает быстрее С/C++. Как скриптовый язык может быть быстрее/справляться лучше нативного языка?
                  • 0
                    Я сказал «быстрее»? Я сказал «лучше»! Если бы Вам хоть раз доводилось серьезно воспользоваться регулярными выражениями, которые когда-то давно были многими языками из Перла «слизаны», то разные значения этих слов были бы вам понятны. Будьте так добры, читать внимательнее, перед тем как отвечаете и называете мои слова «напоминающими бред». О производительности Perl vs C я не сказал ни слова.
                    • 0
                      Давайте смотреть реальности в глаза. Если какой-то функционал (который удобнее) реализован в Перле — его можно реализовать на любом языке, раз мы не говорим о быстродействии (в т.ч. и PHP сюда включим).

                      Поэтому говорить, что какой-то язык справляется с чем-то лучше, по крайней мере, некорректно. То, что где-то идет «в комплекте» библиотека-враппер — ни о чем не говорит. Напишите его и не морочьте людям голову — понять могут неправильно.

                      > Я сказал «быстрее»? Я сказал «лучше»!… Будьте так добры, читать внимательнее
                      Вы сами прочтите внимательно. «… быть быстрее/справляться лучше нативного...»

                      ЗЫ: Что за глупость «слизаны у PERL»? До перл-совместимых были BRE (UNIX) и ERE(POSIX). Многие вещи PCRE унаследовал от POSIX, который был расширением UNIX. Получается, что PERL их слизал и расширил/изменил?: D

                      Давайте еще скажем, что PHP слизал синтаксис у С/С++? За сим откланиваюсь. Смысла спорить нет.
  • 0
    ua.php.net/manual/ru/function.pcntl-fork.php

    имхо удобнее

    а вообще многопоточные приложения пишу либо на пайтоне либо на перле — мне кажется там удобнее
  • 0
    Простите, но зачем такой изврат, если есть pcntl? Хотите — напишу руководство, как раз сейчас занимаюсь многопотоковым приложением.
    • 0
      Едрить-колотить =) pcntl — это межПРОЦЕССНОЕ взаимодействие и контроль. Какие потоки!? Давайте вещи своими именами называть.
    • 0
      PS: если напишете про многоПРОЦЕССНОЕ приложение, то мне лично будет интересно.
    • 0
      Напишите, будет интересно почитать.
  • +1
    Ну после фразы
    нескольких (однотипных) потоков, выполняющихся «параллельно», то есть без упорядочивания по времени — выполнился один, пошел следующий.
    уже не хочется читать про очередную «многопоточность в пхп»…
    • 0
      Вы, наверно, неправильно меня поняли. Пояснение моих слов двумя комментариями ниже.
  • 0
    1. используйте raw sockets
    2. обрабатывайте коды состояний/ответов желательно по всем платформам.
    3. поправте работу с таймаутами
    4. отдельными процессами запускайте многопоточное получение ип адресов удаленных хостов
  • 0
    «Суть многопоточности (для приложения) состоит в том, что процесс может состоять из нескольких (однотипных) потоков, выполняющихся «параллельно», то есть без упорядочивания по времени — выполнился один, пошел следующий...»

    Вообще-то, многопоточность — это когда два потока работабт ОДНОВРЕМЕННО в пределах одной программы, а не по порядку.
    • 0
      Разумеется. Я имел в виду, что если один из двух закончился, то нет ожидания, пока отработает второй, а сразу запускается третий.
    • 0
      +1

      «Сутью многопоточности является квазимногозадачность на уровне одного исполняемого процесса, то есть все потоки выполняются в адресном пространстве процесса.». Вика.
  • 0
    Подскажите пожалуйста у всех ли нормально работает? У меня в PHP 5.2.2 установка stream_set_blocking($fsock, 0);
    дает ошибки fwrite(): send of 256 bytes failed with errno=11
    В чем может быть дело?
  • 0
    Подскажите пожалуйста у всех ли нормально работает? У меня в PHP 5.2.2 установка stream_set_blocking($fsock, 0);
    дает ошибки fwrite(): send of 256 bytes failed with errno=11
    В чем может быть дело?
    • 0
      Вот прикольно, на хабре баг, а мне минус в карму поставили :)
  • 0
    Интересно появится ли когда нибудь в PHP многопоточность. В 6й версии тоже вроде не планируется, хотя довольно актуальная тема вроде. Но чисто теоретически можно реализовать многопоточность через рассширение на си.
  • 0
    Мне кажется, что многопоточность в PHP — это такой Святой Грааль, Секрет Бессмертия и Вечный Двигатель в одном флаконе.
  • 0
    Я конечно понимаю что это некропостинг, но нельзя ли обновить ссылку, а то она побилась.
  • 0
    Pardon moi за некропостинг, но ссылка бятая =/

    В дополнение к материалу могу сказать, что при доработке класса можно будет выполнять одновременно разнотипные задачи на разных серверах и с разными протоколами. Опробовано — работает =)

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.