I ВСТУПЛЕНИЕ PHP относится к языкам программирования, в которых поддержка многопоточности отсутствует. Но, существует немало задач, где она необходима. В рамках тематики данного форума это могут быть брутеры, спамеры, граберы, чекеры, инвайтеры, гулялки, заливщики. Сразу отмечу, эмулировать многопоточность будем для работы с сетью, не для вычислительных процессов и прочего (ИМХО - здесь PHP не пригоден как интерпритируемый язык в связи со скоростью его выполнения). Итак, рассмотрим способы реализации многопоточности в ПХП. 1. Многопоточность можно реализовать внутри вашего скрипта, создав список неблокирующих сокетов и переодически проверяя отработал поток или нет. Такой подход подробно рассмотрен здесь . Стоит так же отметить, такой же подход использует класс функций multi_ библиотеки CURL. 2. Второй метод основан на эмуляцции многопоточности, используя многозадачность. Другими словами, наш скрипт просто запускает нужное число процессов, распределяя между ними входные данные нужным образом. Этот метод впервые был предложен на ачате здесь , так же интересная реализация этого метода предложена здесь . Я пошёл по второму пути, развил и доработал его. Разработанный скрипт распределяет входные данные, может работать с несколькими исполняемыми скриптами одновременно, собирает результаты работы скриптов по их завершению. II РЕАЛИЗАЦИЯ Функция для запуска эмуляции многопоточности PHP: threads_create( $threads, //число потоков $copy_files, //файлы, нужные для работы каждого потока $create_files, //исходные данные, которые нужно распределить между потоками $run_files, //исполняемые файлы в рамках каждого потока $implode_files //результирующие данные, сформированные каждым из потоков, которые нужно собрать в 1 файл ) Вкратце алгоритм работы: В результате работы функция создаёт папки для каждого потока, копирует туда нужные для работы файлы, разделяет данные между этими папками и запускает каждый исполняемый скрипт. По завершению работы скрипт сохраняет результирующие данные в файл в своей папке, а когда все скрипты отработают, софт соберёт результирующие данные из указанных файлов и разместит их в файле с тем же именем в папке со скриптом. Все созданные промежуточные файлы и папки удаляются. PHP: function threads_create( $threads, $copy_files, $create_files, $run_files, $implode_files=array() ) { $cfs = array(); foreach( $create_files as $fname => $content ) { if( !is_array( $content ) ) { $content = file2array( $fname ); } else { } $cfs[ $fname ] = array_rand_slice( $content, $threads ); } $bat = "@echo off\ncd thread0\n"; $tdir = 'threads-' . randstr(5); mkdir( $tdir ); chdir( $tdir ); for( $i = 0; $i < $threads; $i++ ) { $dir = 'thread' . $i; mkdir( $dir ); foreach( $copy_files as $fname_from => $fname ) copy( '../' . $fname_from, $dir . '/' . $fname ); foreach( array_keys( $cfs ) as $fname ) file_put_contents( $dir . '/' . $fname, str_replace( "\n\n", "\n", implode( "\n", $cfs [$fname] [$i] ) ) ); $bat .= "cd ..\\thread{$i}\n"; foreach( $run_files as $fname => $params ) $bat .= "start php $fname $params\n"; } file_put_contents( 'run.bat', $bat ); exec('run.bat'); unlink('run.bat'); foreach( $implode_files as $if ) { $contents = array(); for( $i = 0; $i < $threads; $i++ ) { $contents []= trim( file_get_contents( 'thread' . $i . "\\" . $if ) ); } file_put_contents( "..\\$if", implode( "\r\n", $contents ), FILE_APPEND ); } for( $i = 0; $i < $threads; $i++ ) { $dir = 'thread' . $i; foreach( array_merge( array_keys( $cfs ), array_keys( $copy_files ) ) as $fname ) unlink( $dir . '/' . $fname ); rmdir( $dir ); } rmdir( $tdir ); } function randel( $array ) { return $array[ mt_rand( 0, count($array) - 1 ) ]; } function randsymb() { $symbs = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; $rand = mt_rand(0,strlen($symbs)-1); return $symbs{$rand}; } function randstr($len) { for($i=0;$i<$len;$i++) { $str .= randsymb(); } return $str; } function file2array( $filename ) { $array = array(); foreach( file( $filename ) as $row ) if( $row = trim( $row ) ) { $array []= $row; } return $array; } function array_rand_slice( $array, $amount ) { shuffle( $array ); $sliced = array(); $step = floor( count( $array ) / $amount ); for( $i = 0; $i < count( $array ); $i += $step ) { $sliced []= array_slice( $array, $i, $step ); } return $sliced; } III ПРИМЕР Рассмотим эмуляцию многопоточности на примере выложенного мню ранее чеккера ВК аккаунтов. Можете скачать и поганять, что бы увидеть как это всё работает. Чеккер распостраняется в виде 3-х файлов: +accs.txt - файл с аккаунтами на чек + do.php - собственно чекер, однопоточный, + make.php - запускает чек ( php make.php ЧИСЛО_ПОТОКОВ ) PHP: if( $threads = $argv[1] ) { include_once('../includes/lib.vk.php'); include_once('../includes/lib.thread.php'); threads_create( $threads, //указываем число потоков, считав его предварительно как первый параметр командной строки array( 'do.php' => 'do.php', //какие файлы копировать в папку к каждому потоку ), array( 'accs.txt' => 'accs.txt', //какие файлы содержат данные, что надо равномерно распределить между всеми потоками ), array( 'do.php' => '', //исполняемые файлы с набором параметров ), array( 'accs.good.txt', //файл гуд акков, который надо собрать в результате работы каждого из потоков 'accs.bad.txt' //файл бед акков ) ); } Спасибо за внимание.
И любой адекватный человек использует для этих целей другой язык программирования. Из-за скорости выполнения и нагрузки он и для работы с сетью с такими "потоками" не особо пригоден. Далее рассмотрим кодэ. Else - пустое место? Сурово Причем нигде не указано, что решение исключительно под win. Ты не поверишь, но существует функция array_rand. Опять модная функция. Неведомая проверка тоже радует, ТС, специально для тебя у функции file есть специальный флаг FILE_IGNORE_NEW_LINES. Бле, пересчет размера массива при каждой итерации... А тут в первой функции мы видим пересчет длины статической строки при каждом вызове. Не проще ли было воспользоваться функцией chr (например, chr(mt_rand(0x30, 127)))? А во второй функции переменная $str вообще не инициализирована изначально. Ни в одной функции нет вообще никакой обработки ошибок. Даже если код где-то навернется, все равно продолжится его выполнение дальше. А навернуться тут очень много шансов.
А ты загляни в топик продаж - таммного однопоточного софта на ПХП ты ещё скажи что для создания сайтов не пригоден основные траты времени при работе сетевого приложения идут на запросы, так что интерпритируемый или компилируемый язык - это здесь не критично. array_rand возвращает ключ, моя возвращает значение. PHP хеширует такие вещи Проще с точки зрения скорости выполнения программы, но сложнее с точки зрения её читаемости Изначально она и так пуста/нул/ноль. Этот код работал уже годика полтора З.Ы.: Catbert, чего так нервно? давно не трахался? З.Ы.2: я не претендую на звание мега-кул программера и знаю свой уровень, если где допускаю ошибку - можно просто сказать, без понтов училки-задротки. и писал этот топик не для того что бы показать какой я крутой задрот, а что бы помочь кому-то
А в мире много безработных и нищих - это повод на них равняться? Правда? Т.е. ты утверждаешь что при работе с сетью пхп покажет скорость аналогичную программе написанной на с++ скажем? Т.е. лучше написать mt_rand( 0, count($array) - 1 , чем array_rand($array) ? Ну да, конечно, лучше вызвать две функции чем одну. $array[mt_rand( 0, count($array) - 1]; -> $array[array_rand($array)]; В ассоциативный массив заносит штоле? И Лада Калина может ездить полтора годика без поломки, однако она ни разу не пример качественного автомобилестроения.
Все на пхп и пишут из-за того, что язык прост как зубочистка. А вы своей статьей провоцируете таких горе-кодеров не развиваться, изучая новые языки, а выжимать бесполезные вещи из всё того же php. Хеширует? Может быть, кеширует? А вообще, я даже проверил это ради интереса. Ничего он там не кеширует. PHP: <?php function microtime_float() { list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); } $arr = Array(); for($i=0; $i<200000; $i++) //заполняем массив побольше $arr[$i] = mt_rand(1,10); $time_start = microtime_float(); for($i=0; $i<count($arr); $i++) //Тест 1 $arr[$i] = mt_rand(1,10); $time_end = microtime_float(); $time = $time_end - $time_start; print "Test 1: $time<br>"; $time_start = microtime_float(); for($i=0, $cnt = count($arr); $i<$cnt; $i++) //Тест 2 $arr[$i] = mt_rand(1,10); $time_end = microtime_float(); $time = $time_end - $time_start; print "Test 2: $time<br>"; ?> Результаты: Code: Test 1: 0.170279979706 Test 2: 0.112259864807 А тут по-моему скорость важнее. А читаемость и так и так нормальна. Все же, она не пуста, она неопределена. Коды во многих программах работают годика полтора, пока кто-то не находит в них уязвимость и разработчики не начинают паниковать. Ну это так, к слову.
Ох вы и злые... я ж не софт для запуска шатла писал, всё к словам да мелочам придираетесь. Уйду я от вас Шутка, не дождётесь Скорость будет сравнима, т.е. отличаться будет не в десятки и сотни раз, а возможно даже и не в разы. Catbert, чего ты злой такой? и всё к мелочам приколупываешься? Согласен, хотя и тут накодили такие вещи как CakePHP - довольно мощный фреймвёк. Ну вот, мы друг-друга поняли ну в рамках данного скрипта это приблизительно одно и то же, ну а если кодить строго и по канонам то да, ты прав.