Some time ago, I’ve wrote a small server in PHP. Nothing fancy. It would listen on a socket and when a new client would connect, the server would start a new thread and manage the client’s request. Since threading it’s not available in PHP, I’ve emulated the threads with child processes which are available in php. A thread object simply encapsulates a new process started with pnctl_fork() and emulates – to some extent – the behaviour of the java.lang.Thread class, the main difference being that in my implementation, you don’t extend the Thread class, you simply provide the name of a callback function in the constructor.
A simple multithreaded application would look like this:
require_once( 'Thread.php' );
// test to see if threading is available
if( ! Thread::available() ) {
die( 'Threads not supported' );
}
// function to be ran on separate threads
function paralel( $_limit, $_name ) {
for ( $index = 0; $index < $_limit; $index++ ) {
echo 'Now running thread ' . $_name . PHP_EOL;
sleep( 1 );
}
}
// create 2 thread objects
$t1 = new Thread( 'paralel' );
$t2 = new Thread( 'paralel' );
// start them
$t1->start( 10, 't1' );
$t2->start( 10, 't2' );
// keep the program running until the threads finish
while( $t1->isAlive() && $t2->isAlive() ) {
}
This will display Now running thread 1 and Now running thread 2 messages with 1 second delays. I know, not that impressive, but hey, it’s multithreaded.
PHP threading will only work on Unix and Linux systems, because pnctl_fork is nothing more than a wrapper for the fork() function from unistd.h and it’s not available under Microsoft operating systems.
I know that the first example was pretty lame, but there are some more interesting things you could do with threads in PHP. For instance, if you need to do some server side processing of all the images in a directory, a multithreaded approach will be much faster.
require_once( 'Thread.php' );
// test to see if threading is available
if( ! Thread::available() ) {
die( 'Threads not supported' );
}
// define the function to be run as a separate thread
function processImage( $_image ) {
// expensive image processing logic here
}
$threads = array();
$index = 0;
foreach( new DirectoryIterator( '/path/to/images' ) as $item ) {
if( $item->isFile() ) {
$threads[$index] = new Thread( 'processImage' );
$threads[$index]->start( $item->getPathname() );
++$index;
}
}
// wait for all the threads to finish
while( !empty( $threads ) ) {
foreach( $threads as $index => $thread ) {
if( ! $thread->isAlive() ) {
unset( $threads[$index] );
}
}
// let the CPU do its work
sleep( 1 );
}
PS: it’s a bad practice to keep looping in order to wait for a thread to finish. An ongoing empty loop will quickly boost your CPU ‘s load to 100%. If you need your processor free (and you need it), simply send the current (looping) thread to sleep and let the others execute.
// wait for thread - bad approach (overloads the CPU)
while ( $thread->isAlive() ) {
}
// wait for thread - correct approach
while( $thread->isAlive() ) {
sleep( 1 );
}
Download Thread.php
Here you go: Thread.php. Just click the link to download the class. If you have a better approach to this issue or think that the original class could be improved, don’t be shy and leave a comment below. Credits will be given.
[...] the original: Multithreading in php Related ArticlesBookmarksTags PHP PHP is a computer scripting language. Originally [...]
Thanks!
Did you try it on a live project? Can we see it at work?
Unfortunatelly “live” , “at work” no because of M$ OS.
But i’ll use it for my scripts in Ubuntu!
I’ve used it on a project, but it’s only available in intranet. But it works and that’s all that matters. If you have any suggestions of improvement, so share
Hi guys,
My PC worked not correctly, too much mistakes and buggs. Please, help me to fix buggs on my computer.
My operation system is Win Vista.
Thx,
upsemshop
At line 170, there is an error.
pcntl_waitpid( $this->pid, $status = 0 );
You never use the variable $status anyway, so it doesn’t hurt. But if you ever decide to use the $status variable, passing in $status = 0 does not pass the variable to the function, it passes the value of the assignment, 0.
If you set your error reporting to strict, it will complain that:
“Only variables should be passed by reference”
Otherwise, thanks for sharing your code.
10x man, I’ll look into it and fix it later today. Sometime bugs escape one programmer just to be caught by another. That’s the beauty of Open Source.
I had a look at the code and it seems it was better the way it was. I made some tests, and, as if turned out, if I change that line and remove the $status variable, like such:
it will yield an fatal error, saying:
I always want to pass in 0 as an argument there, so there are two ways in which that can be achieved:
Hope it’s clear for everybody now.
Why do you want to pass a zero in there? That parameter is not expecting a _value_, it’s expecting a _reference_. PHP can can put the real status value in it and give it back to you so that you can check against it later.
See the functions pcntl_wif*()
I hope that made sense.
I’ve browsed the manual, as this entry is over one year old and I can’t remember why I took some decisions back then. It seems that you must always pass in a variable for the status to the function, in order to work. I’m not interested in the returned status, so I’ve passed in a zero variable.
Thanks for the example code. Any idea how I would use that in an Apache server that executes PHP scripts? I’m on Ubuntu and it seems as if pcntl_fork() is not available in the PHP that is in the apache. I tried the solution in
http://www.php.net/manual/en/ref.pcntl.php#91224
but it does not seem to work for me.
Any ideas?
Thanks,
George
It won’t work like this. I think the best way to achieve multithreading is dropping PHP and switch to python or something else. Or rewrite in a different language the part you want to be multithreaded.
Hi,
The function I’d like to thread returns a string, is it possible to retrieve that somehow and let them set in a result array in the main code starting the threads for example?
Thanks in advance, Zoli
Good one, Zoli! I’ll update the Thread.php file in the future. Until then, you need to do the following: add “return” in front of the call_user_func_array() and
call_user_func() calls so that the start() method will return the original function’s result. Like such:
// child pcntl_signal( SIGTERM, array( $this, 'signalHandler' ) ); $arguments = func_get_args(); if ( !empty( $arguments ) ) { return call_user_func_array( $this->runnable, $arguments ); } else { return call_user_func( $this->runnable ); } exit( 0 );This is untested code, but it *should* work!
Thanks for that. I learned a lot from your code. A suggestion to an otherwise excellent class:
It is allowed for the first parameter of call_user_func_array to be an array(class, ‘method’). So, there is a problem with function_exists in runnableOk. Besides, if it is_callable then function_exists. So I don’t think you need to check both.
Hi! Great script!
I’ve been testing the Zoli idea and the “return” aproximation and it does not work… mainly because the child dies and there is no communication between parent and child…
They are two separated processes, so… any idea to get returned data to the parent from the children function? Maybe sockets??
Hi! I’ve found how to return data from child to parent, using pipes:
In class Thread:
/** * Starts the thread, all the parameters are passed to the callback function * @return void */ public function start() { $status = 0; $results = null; $pid = pcntl_fork(); if( $pid == -1 ) { //error forking, no child is created throw new Exception( $this->getError( Thread::COULD_NOT_FORK ), Thread::COULD_NOT_FORK ); }else if ( $pid ) {// parent $this->pid = $pid; } else { // child $this->pid = posix_getpid();//pid (child) $this->ppid = posix_getppid();//pid (parent) pcntl_signal( SIGTERM, array( $this, 'signalHandler' ) ); $array_args = func_get_args(); if ( !empty( $array_args ) ) { $results = call_user_func_array( $this->runnable, $array_args ); }else{ $results = call_user_func( $this->runnable ); } $pipe = "/tmp/pipe_"..$this->pid;//pid is known by parent if(!file_exists($pipe)) {//child talks to parent using this pipe umask(0); posix_mkfifo($pipe, 0600); } //we have to open the pipe and send the data serialized $pipe_descriptor = fopen($pipe, 'w'); fwrite($pipe_descriptor, serialize( $results ) ); //and kill the child using posix_kill ( exit(0) duplicates headers!! ) posix_kill( $this->pid , SIGKILL); exit(0); } }In function which uses Thread:
$sleep_microseconds = 200000; // we don't want to achieve 100% CPU load! //start multiple threads!! for ($i = 0; $i start( 'param1','param2' ); } } //We are the parent... childs never reach this part of the code!! //Parent has to read child's pipes... Communication between parents and childrens is necesary in our society! while (!empty( $threads )){//while any child is alive... foreach($threads as $index => $thread){ $child_pipe = "/tmp/pipe_".$thread->getPid();//this pipe communicate the parent with one of his childs... look at Thread->start() method, in both places (child and parent) the pipe name must be the same! if (file_exists($child_pipe)){//if pipe exists, we (the parent) open it, listen to our child, and when the child has finished, the child will die and the parent close the pipe between them $file_descriptor = fopen( $child_pipe, "r"); $child_response = ""; while (!feof($file_descriptor)){//while pipe is open, parent continues reading $child_response .= fread($file_descriptor, 8192); } //we have the child data in the parent, but serialized: $array_responses[ $index ] = unserialize( $child_response ); //now, child is dead, and parent close the pipe unlink( $child_pipe ); unset($threads[$index]);//and remove the child from our array } } //parent must sleep for a while, because we don't want to achieve 100% CPU load! usleep( $sleep_microseconds ); } //now, we have all data from the forked childs in $array_responsesI needed to pass a value by reference to the “threaded” function and noticed that in its current instance, this class only passes by ref, this was changed near line 147 by using:
$stack = debug_backtrace(); $arguments = array(); if (isset($stack[0]["args"])) { for($i=0; $i > count($stack[0]['args']); $i++) { $arguments[$i] = & $stack[0]['args'][$i]; } }I’m not sure of the performance hit by doing this, but it works.
Further to the above, I was mistaken, that obviously doesn’t work, all it does is stop the warnings.
It only appeared to be working based on the input I was testing with, oh well.
Encapsulate the value you want to pass on in an object. Since objects are always passed by reference in PHP, it should do the trick.
The threading itself worked like a charm, unfortunately my singleton mysql wrapper wouldn’t work with it as it always complained about the database going away.
Try opening a permanent connection to the MySQL server!
[...] l’ai donc réécrit en PHP en utilisant cette classe qui permet de gérer des threads (Attention, celle-ci utilise l’extension pcntl de PHP). [...]
Thanks for the great class! This has helped me with the question “What should I use for my PHP project as a command-line multithreaded net app: Python or Java”. I’ll go all the way with PHP.
Thanks for this, I’d like to suggest an addition. I needed to call a method in a class, but runnableOK was returning false as a method isn’t a function… So, assuming i’m passing the object instance and method name in an array like this: $t = new Thread(array($this, ‘publicmethod’)), the following change will allow it.
public static function runnableOk( $_runnable ) { // check for method existance if (is_array($_runnable)){ return (method_exists(get_class($_runnable[0]), $_runnable[1]) && is_callable($_runnable) ); } else{ return ( function_exists( $_runnable ) && is_callable( $_runnable ) ); } }just make sure the method isn’t private! Or, instead of passing the object, you could modify it to accept the class name.
Hi,
Seems like a very nice class, and I’ve tried to implement it into an IRC bot written in PHP, but I can’t get it to work properly without the bot dying. After trying Ricardo’s pipe trick, i got a bit further, well the bot doesn’t die after execution, but doesn’t open the pipe either.
I wanted to try to implement some sort of threading mechanism, because the bot might have to execute some heavy commands every now and then, that is – commands which consumes a great amount of time (i.e. a ping command), which stalls the but while executing – so my thoughts were, launch the command in a new thread, and write back the reponse (when done) to the user/channel – while being able to make the bot do other tasks, while processing.
Any ideas? or is this just not possible?
Thanks,
/Tim
Nice class, added a few lines to support static functions in objects:
/** * Implements threading in PHP * * @package * @version 1.0.0 - stable * @author Tudor Barbu * @copyright MIT */ class Core_Thread { const FUNCTION_NOT_CALLABLE = 10; const COULD_NOT_FORK = 15; /** * possible errors * * @var array */ private $errors = array( Core_Thread::FUNCTION_NOT_CALLABLE => 'You must specify a valid function name that can be called from the current scope.', Core_Thread::COULD_NOT_FORK => 'pcntl_fork() returned a status of -1. No new process was created', ); /** * callback for the function that should * run as a separate thread * * @var callback */ protected $runnable; protected $object; /** * holds the current process id * * @var integer */ private $pid; /** * checks if threading is supported by the current * PHP configuration * * @return boolean */ public static function available() { $required_functions = array( 'pcntl_fork', ); foreach( $required_functions as $function ) { if ( !function_exists( $function ) ) { return false; } } return true; } /** * class constructor - you can pass * the callback function as an argument * * @param callback $_runnable */ public function __construct( $_runnable = null, $_object = null ) { if( $_runnable !== null ) { $this->setRunnable( $_runnable, $_object ); } } /** * sets the callback * * @param callback $_runnable * @return callback */ public function setRunnable( $_runnable, $_object = null ) { if( self::runnableOk( $_runnable, $_object ) ) { $this->runnable = $_runnable; $this->object = $_object; } else { throw new Core_Exception( $this->getError( Core_Thread::FUNCTION_NOT_CALLABLE ), Core_Thread::FUNCTION_NOT_CALLABLE ); } } /** * gets the callback * * @return callback */ public function getRunnable() { if($this->object) return array($this->object, $this->runnable); return $this->runnable ; } /** * checks if the callback is ok (the function/method * actually exists and is runnable from the current * context) * * can be called statically * * @param callback $_runnable * @return boolean */ public static function runnableOk( $_runnable, $_object = null ) { if($_object !== null) return ( method_exists( $_object, $_runnable ) && is_callable( array($_object, $_runnable ) ) ); else return ( function_exists( $_runnable ) && is_callable( $_runnable ) ); } /** * returns the process id (pid) of the simulated thread * * @return int */ public function getPid() { return $this->pid; } /** * checks if the child thread is alive * * @return boolean */ public function isAlive() { $pid = pcntl_waitpid( $this->pid, $status, WNOHANG ); return ( $pid === 0 ); } /** * starts the thread, all the parameters are * passed to the callback function * * @return void */ public function start() { $pid = pcntl_fork(); if( $pid == -1 ) { throw new Core_Exception( $this->getError( Core_Thread::COULD_NOT_FORK ), Core_Thread::COULD_NOT_FORK ); } if( $pid ) { // parent $this->pid = $pid; } else { // child pcntl_signal( SIGTERM, array( $this, 'signalHandler' ) ); $arguments = func_get_args(); if ( !empty( $arguments ) ) { call_user_func_array( $this->getRunnable(), $arguments ); } else { call_user_func( $this->getRunnable() ); } exit( 0 ); } } /** * attempts to stop the thread * returns true on success and false otherwise * * @param integer $_signal - SIGKILL/SIGTERM * @param boolean $_wait */ public function stop( $_signal = SIGKILL, $_wait = false ) { if( $this->isAlive() ) { posix_kill( $this->pid, $_signal ); if( $_wait ) { pcntl_waitpid( $this->pid, $status = 0 ); } } } /** * alias of stop(); * * @return boolean */ public function kill( $_signal = SIGKILL, $_wait = false ) { return $this->stop( $_signal, $_wait ); } /** * gets the error's message based on * its id * * @param integer $_code * @return string */ public function getError( $_code ) { if ( isset( $this->errors[$_code] ) ) { return $this->errors[$_code]; } else { return 'No such error code ' . $_code . '! Quit inventing errors!!!'; } } /** * signal handler * * @param integer $_signal */ protected function signalHandler( $_signal ) { switch( $_signal ) { case SIGTERM: exit( 0 ); break; } } } // EOFThanks for sharing this! Inspired by your work I published Threadi today.
@see
http://www.typo3-media.com/blog/multithreating-in-php.html
https://github.com/danielpoe/Threadi
Thanks mate!
Hi .
I want to use this class in my php code in Ubuntu. but i dont know why it not worked here.
When i run the project:
if (Thread::available()) { die( 'Threads not supported' ); }This message is shown:
Threads not supported
How can i solve this problem?
Make sure that the pnctl library is installed http://www.php.net/manual/en/book.pcntl.php . I think it’s in the repositories.
how can i check the pnctl library is installed? Please describe me what do i do to use this class?
Do i use this class(Thread.php) in windws os?
Thanks
I need multithreading to do some work.Please help me how i can use this class. I write the frist example of this page, but i dont have the problem: ‘Threads not supported’
How can i check pnctl library is installed? How can i?
With Regards.Mojtaba
If it fails with that message, then the library is not installed. I just posted a link in the previous comment to the PHP manual’s section on the pnctl. Read it, install pnctl and it will work…
Thanks very much
I have a question about using threading in php:
I need to check some conditions in my code and if the conditions were true then insert some information to mysql database and redirect the user to other pages. I dont like the user wait so that the informations is recorded to database and then redirect to other pages. Do i can insert information to my database as threading?
If i use this code at the end of my code: While(t1->isAlive()){}…
Then the user should be waiting so that transaction is compeleted and then redirect. So How can i solve this problem?
With Regards.Mojtaba
Writing input to the db takes very little time and you really shouldn’t worry about that. This was only used in a CLI environment so I don’t know its exact behavior under Apache or whatever server you might be using.
Hi Tudor, greetings from Ecuador…. I’ve tried your code sending simple parameters to start function (integer and string values) but if I use complex objects I cannot reach functions from my nested variable in the object…. I’m not sure if it is clear…
Thanks so much in advance for the help you could provide me…
Can you post some code?
[...] już szczęśliwym posiadaczem ubuntu, nie stanowi to żadnego problemu. Znalazłem też w sieci fajną klasę, która umożliwia czytelniejszą obsługę wątków w obiektowym stylu. Dzięki tej klasie obsługa wątków jest dziecinnie prosta. Autor zamieścił przykłady jej [...]
hi Tudo,
I need urgent help in this. I am trying to use your thread.php ro read multiple file but when i call processImage function then it does not come back to main function. Its not going to second loop to read files. Just hangs there itself.
CAn you guide me.
Thanks,
Hello Tudor,
What benefits are there to emulating multi-threading in PHP?
Don’t get me wrong, you have come up with a working thread emulation, but what does it actually achieve?
The emulation will incur overhead, but the “threads” will not be assigned to separate processors by the OS. If anything using emulated threads is only going to slow an application down (as opposed to boosting performance).
Cheers,
Dude…seriously!!! Do some reading…
[...] die skripten multithreaded laufen lasse: hierbei verwende ich einen wrapper für pcntl_fork() (vgl.HIER). das skript erzeugt damit für die ersten 5-10 sekunden vollast auf allen 8 threads (oder sovielen [...]
[...] via their port numbers (baibhavsingh.wordpress.com)You’ve Been Hacked! (famousbloggers.net)Thread class for multithreading in PHP (motane.lu)How do I increase upload file limit from 2MB to 10MB under Apache 2 UNIX / Linux web [...]
[...] danke für den Hinweis. War nur durch das drauf gekommen -> Multithreading PHP Script läuft jetzt auch ganz gut ohne das ganze, aber kurze Frage noch. Wird bei PHP-Code: [...]
Hello,
I just needed a help regarding multithreading in php.So i visited it.
I follow up the source code of multithreading.but in the source m having an error.
Im having problem in the above line.Can anyone help me out ?
Thanx
[...] Outra coisa brutal que me apercebi, é que dá para fazer MultiThreading com PHP, através de uma classe implementada por um individuo cujo nickname é Tudor. Podem aceder ao seu blog e ter acesso a mais especificações sobre a classe Thread() aqui: http://blog.motane.lu/2009/01/02/multithreading-in-php/ [...]
Hello,
Tudor do you have any idea how to create a shared memory between forks? Im realy newbie in this topic
Regards,
cojack.
Thanks for the code, much appreciated!
I’ve been trying to run a modified version of the 2nd example on my box, it works, but somewhere after executing the threads it stops if I enable the sleep(1); call *or* if I use this line
while( !empty($threads) )Changing while to if fix the problem but well the logic is then broken.
The code is here, I’d be infinitely grateful if you can shed some light on it:
// ================================================ // $threads = array(); // Create and start threads for ($i = 1; $i start( $base_name, $file_name, $folder_name, $i ); $threads[] = array($i - 1 => $thread); } // Wait for all the threads to finish $i = 0; while( !empty($threads) ) { foreach( $threads as $i => &$thread ) { if ( !$thread[$i]->isAlive() ) { unset( $threads[$i] ); // die; // unset( $thread[$i] ); } } // Let the CPU do its work sleep(1); } // ================================================ //Thanks in advance,
Gdhami.
[...] Multithreading in php. Trochę na temat wielowątkowości w PHP. [...]
Hi, I was thinking about something very similar, so thanks for saving my time
I have one note, the name is not picked right. Lot of people might be confused, because parallelism via processes is very different than via threads. Threads have shared memory, are run in one process and so on.
So much more suitable name should be Process.
Still thanks for the work!
is there a sollution for windows system?
I don’t know! Might be, but I never use windows….
[...] By default, PHP has no built-in support for multithreading, but Tudor Barbu has developed multithreading class for PHP. [...]
[...] to make the page load more quickly, I can use a template with the code I found on this PHP Multithreading site. Share [...]
is there a sollution for windows system?
Read the comment above yours…
[...] level support, there is a guy who created a class which mocks the JAVA Threading here is the link: http://blog.motane.lu/2009/01/02…This answer .Please specify the necessary improvements. Edit Link Text Show answer summary [...]
If you are talking about Windows, in most of the cases the discussion involves .NET. Of course..you can achieve multithreading by interoping with Java, C++ etc., but since .NET always come in handy for me, I can recommend you this http://www.facebook.com/note.php?note_id=281965971827784
Hi,
Thanks for your information
how to use this for search?
search result will execute same window but override previous one
My post is about achieving multithreading in general, not on a specific case. Of course, you are limited to the single main thread of PHP but which can spawn multiple child threads by interoping, for example, with .net.
You can think of it like this: PHP thread would pass a list of “operations” to be executed on different threads by .net. Instead of having them waiting one for eachother, they could run in parallel. Of course, you can not overcome the limitation of the PHP thread, but there is still a slight gain on performance.
Why use the loop to keep things alive?
You can just set the time limit to 0 and only when one thread closes you can check if there are any other working if not exit.
I think you might spare some resources.
I am working a lot with socket listeners built in PHP and Python… so they are never supposed to stop and the PHP version works very neat like that using quite few resources.
what just writing a plugin for sonic daemon?
what do you think about this solution? (Runs on Linux (slackvare) 2.6.27.7)
PHP 5.2.11 (cli) (built: Oct 2 2009 17:30:20)
require_once( 'Thread.php' ); if ( function_exists('sem_get') )echo "sem"; // test to see if threading is available if( ! Thread::available() ) { die( 'Threads not supported' ); } // function to be ran on separate threads function paralel( $_limit, $_name ,$lock) { sem_acquire($lock); for ( $index = 0; $index start( 10, 't1',$s1); $s2 = sem_get(2); $t2->start( 10, 't2',$s2); // keep the program running until the threads finish sem_acquire($s1); sem_acquire($s2); /* while( $t1->isAlive() && $t2->isAlive() ) {}//*/I don’t think your code got pasted right. Use
[code lang=”php”] … [/code]
to paste properly.
Awesome! There’s hardly any good implementations of forking in php available online, and this one is definitely the best!
Cheers mate!
Very nice! Thanks for sharing.
Hi !!!
I am trying to use this above example. I am working in WAMP. When i am running the Parallel-Returnable.php file its shows Fatal error: Class ‘Threadi_Thread_NonThread’ not found
And i want to know how to enable pcntl in WAMP ?
Please help me to solve this.
WIth Thanks & Regards,
Sanjay
http://sanjoyinfoworld.blogspot.in
Sorry mate, I did not write Threadi, so I can’t offer support. You should contact the author, his name is Daniel Pötzinger and he blogs at http://www.typo3-media.com/blog/
However, based on your error – class not found – you didn’t include the library correctly. But if you’re using a windows system, it won’t work as it relies on the pnctl_fork() function to spawn new “threads”. Just read the manual: http://www.php.net/manual/en/book.pcntl.php
Good luck
t.
[...] For Unix we have http://www.php.net/manual/en/intro.posix.php and http://www.php.net/manual/en/intro.pcntl.php which are a set of complementary libraries that allows process manipulation operations. Let me repeat that: “process manipulation operations”… since there is nothing mentioned about threading, you can simply put it this way: PHP doesn’t natively support threading in Unix through the libraries mentioned above, instead it supports process forking. As you may already noticed, I used the term of “natively” because you can achive multithreading by interoping with languages like Java, C / C++ or even .NET through Mono. If you may wonder what are the advantages of using threads over processes in general, read this http://www.programmerinterview.com/index.php/operating-systems/thread-vs-process/; in particular, each language can have it’s own mechanisms of dealing with threads. A nice article on “multithreading” in PHP can be found on my comrade’s blog Tudor a.k.a. motanelu http://blog.motane.lu/2009/01/02/multithreading-in-php/. [...]
Hello they call me Gabe I love handbags and all kinds of other things as well!
Wanna use objects and his methods or static methods?
Step 1: Change the method Thread::runnableOk to this:
public static function runnableOk( $_runnable ) { if (is_array($_runnable) && count($_runnable) == 2 ) { return method_exists($_runnable[0], $_runnable[1]); } return ( function_exists( $_runnable ) && is_callable( $_runnable ) ); }Step 2: Use this code to use you objects
class MyClass { // function to be ran on separate threads function paralel( $_limit, $_name ) { for ( $index = 0; $index < $_limit; $index++ ) { echo 'Now running thread ' . $_name . PHP_EOL; sleep( 1 ); } } public static function staticMethod ( $_limit, $_name ) { for ( $index = 0; $index < $_limit; $index++ ) { echo 'Now running thread static ' . $_name . PHP_EOL; sleep( 1 ); } } } $m1 = new MyClass(); // create 2 thread objects $t1 = new Thread( array($m1,'paralel') ); $t2 = new Thread( array('MyClass','staticMethod') );[...] [...]
[...] An example daemon is listed below, the class requires the PHP pcntl extension (*nix only) & Tudor Barbu’s excellent Thread class → [...]
I did some of php coding for electriccars4kids.org
Thank you for sharing!
Regarding threading and MySQL (or probably any database server), here are my findings which might help someone else. Generally, launching a new thread “duplicates” all the variables and memory contents of the parent and your child starts with all of it as “baggage”. This includes your current connection to MySQL. As long as your parent (or a second child) doesn’t use that connection, you can use it from your child without any problems. If you have multiple children using the database, each child should open it’s own connection (that kind of makes sense).
However, PHP screws you as soon as your first child ends. As we know, PHP automatically closes connections to MySQL once a script (e.g. your child) ends. This unfortunately includes the connection the child inherited initially from the parent. This means that as soon as one of your child processes has ended, your parent process will have to reconnect to MySQL in order to do anything with the database – or you will get the “MySQL has gone away” error.
In order to keep connections clearly assigned to each thread, I recommend to:
- open one new connection per child
- store the connection resource in a variable and always the identifier for any mysql_* commands. If you use mysqli, use the object oriented aproach and create a new mysqli-object for each thread.
- remember that your parent’s mysql connection will be broken as soon as the first child process has ended. your parent will need to reconnect to MySQL.
I like you simple implementation, I see many threads in my task manager after running your script. I found on Git hub similar project which work better for me. https://github.com/kulikov/php-threads-manager
For those interested in parallel processing you can check out Gearman. Works with PHP.
http://gearman.org/
Hi Tudor
This is a great function you have build. It’s easy to use and work very well.
Is there a build-in function to limit the number processes that runs at the same time? Or have you thought about building it in. I have for example perhaps 500000 loops through some data, that I want to spread out on multi processes, but of course I suppose it will not be good to start 50000 processes at the same time?! Or is there something build into PHP that ensures it doesn’t start to many at the same time?
[...] have the cheapest plan in Dreamhost, which is the Shared Server plan. I tried testing Tudor Barbu's Thread class to see if I could get my site to multi-thread in order to produce pages as quickly as [...]
[...] this one specific threading system i found in php, but it gives a error on index = 0;, any ideas? http://blog.motane.lu/2009/01/02/multithreading-in-php/ any help is appreciated. and i attached the link to the thread script of course, and thats about [...]
Hmm, I expected my code to be recognized, but it’s not syntax highlighted. Can’t find any pointers on how to post code, so here goes another try with [ code ] tags.
I made some code style improvements:
* Made all the code PHP CodeSniffer compatible.
* Fixed return type of kill() from ‘boolean’ to ‘void’. Stop() returns void, so kill() will also return void.
* Removed underscores from local variables. Only private class variables should be prefixed with an underscore.
* Changed function name available() to isAvailable() – function names should always start with a verb.
* Changed function name runnableOk() to isRunnableOk() – same reason
* Changed function name signalHandler() to handleSignal() – same reason
Cheers mate! That was the coding standard of the company I was working for at the time. We weren’t using Zend’s coding standard!
How can I include max number of process?
Hi Tubo,
Your code is very clear.. i tried the example in shared hosting.
This script only runs the first thread…
Can you help me how to do this??
Amazing class man. Thank you! I will post an article about it in my blog soon.
I’ve done some “pipeing” using Memcached. Now this:
$t1 = new Thread( ‘processing’ ); $t1->start();
while( $t1->isAlive() ) {}
echo “Thread return: “.$t1->getReturn();
…works like a charm. (:
[...] “database.php” & “Thread.php” (Thread.php has been downloaded from here). database.php does some trivial tasks after connecting to a remote MondoDb database. Here’s [...]
[...] “database.php” & “Thread.php” (Thread.php has been downloaded from here). database.php does some trivial tasks after connecting to a remote MondoDb database. Here’s [...]
Hi, thanks for sharing, when I used this class (by web browser), the response return ‘Content-type: text/html’ in my browser. Is it some Apache configuration?
[...] clase Thread NO la desarrollamos nosotros, el crédito es de Tudor, pero le hicimos unas modificaciones para que funcionara con clases, solo pasándole como parametro [...]