Basic Threading in Python - Pooling Threads (Page 3 of 4 )
It's important to remember that threads don't start up instantly. Creating too many of them can slow down your application. It takes time to spawn and later kill threads. Threads can also eat up valuable system resources in large applications. This problem is easily solved by creating a set number of threads (a thread pool) and assigning them new tasks, basically recycling them. Connections would be accepted and then pushed to a thread as soon as it finished with the previous client.
If you still don't understand, compare it to a doctor's office. Let's say that there are five doctors. These are our threads. Patients (clients) walk into the office, and if the doctors are busy, they are seated in the waiting room.
Obviously, we'll need something that can transfer client data to our threads without running into problems (it will need to be “thread safe”). Python's Queue module does this for us. Client information is stored in a Queue object, where threads can pull them out when needed.
Let's recreate our server to take advantage of a pool of threads:
import pickle
import Queue
import socket
import threading
# We'll pickle a list of numbers, yet again:
someList = [ 1, 2, 7, 9, 0 ]
pickledList = pickle.dumps ( someList )
# A revised version of our thread class:
class ClientThread ( threading.Thread ):
# Note that we do not override Thread's __init__ method.
# The Queue module makes this not necessary.
def run ( self ):
# Have our thread serve "forever":
while True:
# Get a client out of the queue
client = clientPool.get()
# Check if we actually have an actual client in the client variable:
if client != None:
print 'Received connection:', client [ 1 ] [ 0 ]
client [ 0 ].send ( pickledList )
for x in xrange ( 10 ):
print client [ 0 ].recv ( 1024 )
client [ 0 ].close()
print 'Closed connection:', client [ 1 ] [ 0 ]
# Create our Queue:
clientPool = Queue.Queue ( 0 )
# Start two threads:
for x in xrange ( 2 ):
ClientThread().start()
# Set up the server:
server = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
server.bind ( ( '', 2727 ) )
server.listen ( 5 )
# Have the server serve "forever":
while True:
clientPool.put ( server.accept() )
As you can see, it's a little more complex than our previous server, but it's not amazingly complicated. The client we created in the previous section can be used to test this server, just like the previous server.
Next: More Thread Tricks >>
More Python Articles
More By Peyton McCullough