Improved Thread Simulation Class for PHP

Threads. Most PHP scripts do just fine without them. However, when you venture into the domain of complex and numerous database operations, or when you need to deal with datasources of high latency (to put it plainly, HTTP downloads), the multithreading concept starts to look more attractive.

Threading support in PHP is so-so, and the pcntl extension doesn’t work on Windows. Since I’m too lazy to boot up Linux just for the sake of PHP development, I once again went looking for ways to simulate threads (I’ve written about this before).

I created two classes that use asynchronous HTTP POST requests to simulate multithreading (inspired by this class). The Thread simulates a single thread of execution, whereas ThreadManager is an utility class that makes handling multiple threads easier. The script is a bit too long to post here, so …

Download It

thread.zip (3 KB)
Check the examples below for how to use the classes.

Usage Examples

Here you’ll find a few examples of how to use the two classes. You can also take a look inside thread.php for additional info – most class methods contain explanatory comments.

The next code block is common for all examples. In it I include the thread.php file to get access to the classes, and define the test() function which I will use as the example thread function. test($s) simply sleeps for $s seconds and returns a message telling how long it slept.

include_once("includes/thread.php");
function test($s){
	sleep($s);
	return $s." seconds have passed.";
}

Using the Thread class
This example will create two simulated threads and execute them simultaneously. Note that this isn’t the way I’d do it, as handling multiple threads this way is a hassle. However, it shows the basic functions of the class.

$program_start_time = microtime(true);
 
//Create to thread
$thread1 = new Thread;
/*Set the thread function to execute, and it's arguments. Every 
 argument should be passed as an element of the array. The thread 
 function receives the arguments normally.*/
$thread1->setFunc('test', array(3));
//Start the thread
$thread1->start();
 
$thread2 = new Thread;
$thread2->setFunc('test', array(5));
$thread2->start();
 
//Wait while the threads are running
while (!$thread1->finished || !$thread2->finished){
	$thread1->query(); 
	$thread2->query();
/* query($seconds, $useconds) waits for a specified time for the thread 
and processes it's output (if available), filling the Thread::response and 
Thread::result fields. Returns TRUE if the thread is still running, 
FALSE otherwise.*/
}
 
//Output the results
echo "Thread1 : ", $thread1->result,"<br>\n";
echo "Thread2 : ", $thread2->result,"<br>\n";
 
echo "Total execution time : ".(microtime(true)-$program_start_time)." seconds<br />";

You should get output similar to this :

Thread1 : 3 seconds have passed.
Thread2 : 5 seconds have passed.
Total execution time : 5.01491904259 seconds

Note that you can’t pass resource handles to the thread function. Only variables that can be handled by var_export will work.

Using the ThreadManager class
This is functionally equivalent to the previous example, but more elegant.

$program_start_time = microtime(true);
 
//Create a ThreadManager instance with default settings
$manager = new ThreadManager;
 
//Create and start two threads.
$manager->create_thread('test', array(3));
$manager->create_thread('test', array(5));
 
/* Wait until all threads are finished. ThreadManager::query() 
   processes all threads and returns the number of threads that
   are still executing. Check class definition for details.*/
while ($manager->query());
 
//Output the results
foreach ($manager->finished_threads as $id => $thread){
	echo "Thread '$id' : ", $thread->result,"<br>\n";
}
echo "Total execution time : ".(microtime(true)-$program_start_time)." seconds<br />";

The expected output is something like this :

Thread '_thread_1' : 3 seconds have passed.
Thread '_thread_2' : 5 seconds have passed.
Total execution time : 5.01980900764 seconds

ThreadManager also has a handy pop_finished_thread() function which returns a finished thread and removes it from managers internal lists.

Final Notes

I’m using the class in my DA recommender project and it seems to be working nicely so far. If you have any questions, feel free to comment ;)

Share :
  • Reddit
  • del.icio.us
  • Digg
  • StumbleUpon
  • DZone
  • Ping.fm
  • Sphinn
Related posts :

13 Responses to “Improved Thread Simulation Class for PHP”

  1. 1
    Chris says:

    I have tried the class on two different server environments both give me an error 404!

    Is there anything I need to check?

  2. 2
    Chris says:

    @Chris – I take that back- it now gives me a decoding error. Will keep playing.

  3. 3
    Chris says:

    @Chris – Got the example code to work. However when running it through my code I get a decoding error :o

  4. 4
    White Shadow says:

    @Chris – It has been quite a while since I wrote/used this class, so I don’t have any ideas off-hand. Anyway, I’d start looking at the “The response was :” part to see why the response can’t be decoded, and work from there.

  5. 5
    Balamutikweb says:

    Доброго времени суток! Мне вот тут стало интересно, а есть какие-нибудь он-лайн школы, курсы или что-то подобное, где учат на веб-мастеров? Пытаюсь найти, но ничего не нахожу. Очень хочу стать веб-мастером, слышал, что они хорошо получают. И вообще очень интересно, как это так они работают? И есть ли какие-нибудь спецпредметы, или ещё какие-нибудь специальные дисциплины, которые веб-мастерам знать обязательно? Может кто поможет, если не сложно?
    Слышал, что новичков в этой среде не очень любят – и как тогда быть?

  6. 6
    White Shadow says:

    Извините, а вы случайно не спамер? Коммент вроде бы оффтопик, да и на русском… подозрителъно, тощарищ :P

  7. 7
    NikoRoberts says:

    You have to replace “localhost” in the create_thread function to get rid of the decoding error (Line 287)

    Also the “emtpy” should be “empty” on line 40

    Hope this help anyone in the future.

    Other than that it is great code.

    Thanks!

  8. 8
    White Shadow says:

    Okay, I fixed some of those bugs.

  9. 10
    johnitunes says:

    Yo!
    How are you doing?
    I am new at w-shadow.com and thought I would say HI
    I hope I can become a contributing member!
    Oh yeah… because the economy is so corrupt right now.. I cant afford music.. lol
    Anyone know where I can get free itunes gift cards online?
    Sorry if this is in wrong section admin.. wasnt sure of the right place.

    Thank You!!

  10. [...] http://www.phpclasses.org/browse/package/3953.html [14] Improved Thread Simulation Class for PHP http://w-shadow.com/blog/2008/05/24/improved-thread-simulation-class-for-php/ Author: Anton Vedeshin Categories: Articles Tags: Distributed Computing, PHP Comments (0) [...]

  11. 12
    Bob says:

    I have this working fine on my workstation using XAMPP but when I publish to my production Apache server I get the following

    Decoding error! The response was : HTTP/1.1 404 Not Found Date: Tue, 01 Sep 2009 18:47:57 GMT Server: Apache/2.0.63 (Unix) mod_ssl/2.0.63 OpenSSL/0.9.7a mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635 PHP/5.2.5 Accept-Ranges: bytes Connection: close Transfer-Encoding: chunked Content-Type: text/html 1 1 95
    16 404 Not Found

    43 The server can not find the requested page:

    9 localhost 17 /multithread.php (port 41 80)

    Please forward this error screen to 21 localhost’s WebMaster.

  12. 13
    White Shadow says:

    Looks like the script incorrectly determines the current URL. Take a look at the constructor of the Thread class + the Thread->start() method and see if anything looks wrong to you. Also, you might need to explicitly specify the domain name when creating a thread.

Leave a Reply