multithreading

= Python - Multithreaded Programming =

  



Running several threads is similar to running several different programs concurrently, but with the following benefits: > > A thread has a beginning, an execution sequence, and a conclusion. It has an instruction pointer that keeps track of where within its context it is currently running. > > = Starting a New Thread: = To spawn another thread, you need to call following method available in //thread// module: code thread.start_new_thread ( function, args[, kwargs] ) code || This method call enables a fast and efficient way to create new threads in both Linux and Windows. The method call returns immediately and the child thread starts and calls function with the passed list of //agrs//. When function returns, the thread terminates. Here //args// is a tuple of arguments; use an empty tuple to call function without passing any arguments. //kwargs// is an optional dictionary of keyword arguments.
 *  Multiple threads within a process share the same data space with the main thread and can therefore share information or communicate with each other more easily than if they were separate processes.
 *  Threads sometimes called light-weight processes and they do not require much memory overhead; theycare cheaper than processes.
 *  It can be pre-empted (interrupted)
 *  It can temporarily be put on hold (also known as sleeping) while other threads are running - this is called yielding.

Example:
code #!/usr/bin/python

import thread import time

def print_time( threadName, delay): count = 0 while count < 5: time.sleep(delay) count += 1 print "%s: %s" % ( threadName, time.ctime(time.time) )
 * 1) Define a function for the thread

try: thread.start_new_thread( print_time, ("Thread-1", 2, ) ) thread.start_new_thread( print_time, ("Thread-2", 4, ) ) except: print "Error: unable to start thread"
 * 1) Create two threads as follows

while 1: pass code || <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: justify;">This would produce following result: code <span style="font-family: 'Courier New',monospace; font-size: 12px;">Thread-1: Thu Jan 22 15:42:17 2009 Thread-1: Thu Jan 22 15:42:19 2009 Thread-2: Thu Jan 22 15:42:19 2009 Thread-1: Thu Jan 22 15:42:21 2009 Thread-2: Thu Jan 22 15:42:23 2009 Thread-1: Thu Jan 22 15:42:23 2009 Thread-1: Thu Jan 22 15:42:25 2009 Thread-2: Thu Jan 22 15:42:27 2009 Thread-2: Thu Jan 22 15:42:31 2009 Thread-2: Thu Jan 22 15:42:35 2009 code || <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: justify;">Although it is very effective for low-level threading, but the //thread// module is very limited compared to the newer threading module. = The //Threading// Module: = <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: justify;">The newer threading module included with Python 2.4 provides much more powerful, high-level support for threads than the thread module discussed in the previous section. <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: justify;">The //threading// module exposes all the methods of the //thread// module and provides some additional methods: > > > <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: justify;">In addition to the methods, the threading module has the //Thread// class that implements threading. The methods provided by the //Thread// class are as follows: > > > > > >
 * <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;"> **threading.activeCount:** Returns the number of thread objects that are active.
 * <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;"> **threading.currentThread:** Returns the number of thread objects in the caller's thread control.
 * <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;"> **threading.enumerate:** Returns a list of all thread objects that are currently active.
 * <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;"> **run:** The run method is the entry point for a thread.
 * <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;"> **start:** The start method starts a thread by calling the run method.
 * <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;"> **join([time]):** The join waits for threads to terminate.
 * <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;"> **isAlive:** The isAlive method checks whether a thread is still executing.
 * <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;"> **getName:** The getName method returns the name of a thread.
 * <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;"> **setName:** The setName method sets the name of a thread.

Creating Thread using //Threading// Module:
<span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: justify;">To implement a new thread using the threading module, you have to do the following: > > > <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: justify;">Once you have created the new //Thread// subclass, you can create an instance of it and then start a new thread by invoking the //start// or //run// methods.
 * <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;"> Define a new subclass of the //Thread// class.
 * <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;"> Override the //__init__(self [,args])// method to add additional arguments.
 * <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;"> Then override the run(self [,args]) method to implement what the thread should do when started.

Example:
code <span style="font-family: 'Courier New',monospace; font-size: 12px;">#!/usr/bin/python

import threading import time

exitFlag = 0

class myThread (threading.Thread): def __init__(self, threadID, name, counter): self.threadID = threadID self.name = name self.counter = counter threading.Thread.__init__(self) def run(self): print "Starting " + self.name print_time(self.name, self.counter, 5) print "Exiting " + self.name

def print_time(threadName, delay, counter): while counter: if exitFlag: thread.exit time.sleep(delay) print "%s: %s" % (threadName, time.ctime(time.time)) counter -= 1

thread1 = myThread(1, "Thread-1", 1) thread2 = myThread(2, "Thread-2", 2)
 * 1) Create new threads

thread1.start thread2.run
 * 1) Start new Threads

while thread2.isAlive: if not thread1.isAlive: exitFlag = 1 pass print "Exiting Main Thread" code || <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: justify;">This would produce following result: code <span style="font-family: 'Courier New',monospace; font-size: 12px;">Starting Thread-2 Starting Thread-1 Thread-1: Thu Jan 22 15:53:05 2009 Thread-2: Thu Jan 22 15:53:06 2009 Thread-1: Thu Jan 22 15:53:06 2009 Thread-1: Thu Jan 22 15:53:07 2009 Thread-2: Thu Jan 22 15:53:08 2009 Thread-1: Thu Jan 22 15:53:08 2009 Thread-1: Thu Jan 22 15:53:09 2009 Exiting Thread-1 Thread-2: Thu Jan 22 15:53:10 2009 Thread-2: Thu Jan 22 15:53:12 2009 Thread-2: Thu Jan 22 15:53:14 2009 Exiting Thread-2 Exiting Main Thread code || = Synchronizing Threads: = <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: justify;">The threading module provided with Python includes a simple-to-implement locking mechanism that will allow you to synchronize threads. A new lock is created by calling the //Lock// method, which returns the new lock. <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: justify;">The //acquire(blocking)// method the new lock object would be used to force threads to run synchronously. The optional //blocking// parameter enables you to control whether the thread will wait to acquire the lock. <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: justify;">If //blocking// is set to 0, the thread will return immediately with a 0 value if the lock cannot be acquired and with a 1 if the lock was acquired. If blocking is set to 1, the thread will block and wait for the lock to be released. <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: justify;">The //release// method of the the new lock object would be used to release the lock when it is no longer required.

Example:
code <span style="font-family: 'Courier New',monospace; font-size: 12px;">#!/usr/bin/python

import threading import time

class myThread (threading.Thread): def __init__(self, threadID, name, counter): self.threadID = threadID self.name = name self.counter = counter threading.Thread.__init__(self) def run(self): print "Starting " + self.name # Get lock to synchronize threads threadLock.acquire print_time(self.name, self.counter, 3) # Free lock to release next thread threadLock.release

def print_time(threadName, delay, counter): while counter: time.sleep(delay) print "%s: %s" % (threadName, time.ctime(time.time)) counter -= 1

threadLock = threading.Lock threads = []

thread1 = myThread(1, "Thread-1", 1) thread2 = myThread(2, "Thread-2", 2)
 * 1) Create new threads

thread1.start thread2.start
 * 1) Start new Threads

threads.append(thread1) threads.append(thread2)
 * 1) Add threads to thread list

for t in threads: t.join print "Exiting Main Thread" code || <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: justify;">This would produce following result: code <span style="font-family: 'Courier New',monospace; font-size: 12px;">Starting Thread-1 Starting Thread-2 Thread01: Thu Jan 22 16:04:38 2009 Thread01: Thu Jan 22 16:04:39 2009 Thread01: Thu Jan 22 16:04:40 2009 Thread02: Thu Jan 22 16:04:42 2009 Thread02: Thu Jan 22 16:04:44 2009 Thread02: Thu Jan 22 16:04:46 2009 Exiting Main Thread code || = Multithreaded Priority Queue: = <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: justify;">The //Queue// module allows you to create a new queue object that can hold a specific number of items. There are following methods to control the Queue: > > > > >
 * 1) Wait for all threads to complete
 * <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;"> **get:** The get removes and returns an item from the queue.
 * <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;"> **put:** The put adds item to a queue.
 * <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;"> **qsize :** The qsize returns the number of items that are currently in the queue.
 * <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;"> **empty:** The empty returns True if queue is empty; otherwise, False.
 * <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;"> **full:** the full returns True if queue is full; otherwise, False.

Example:
code <span style="font-family: 'Courier New',monospace; font-size: 12px;">#!/usr/bin/python

import Queue import threading import time

exitFlag = 0

class myThread (threading.Thread): def __init__(self, threadID, name, q): self.threadID = threadID self.name = name self.q = q       threading.Thread.__init__(self) def run(self): print "Starting " + self.name process_data(self.name, self.q)       print "Exiting " + self.name

def process_data(threadName, q): while not exitFlag: queueLock.acquire if not workQueue.empty: data = q.get queueLock.release print "%s processing %s" % (threadName, data) else: queueLock.release time.sleep(1)

threadList = ["Thread-1", "Thread-2", "Thread-3"] nameList = ["One", "Two", "Three", "Four", "Five"] queueLock = threading.Lock workQueue = Queue.Queue(10) threads = [] threadID = 1

for tName in threadList: thread = myThread(threadID, tName, workQueue) thread.start threads.append(thread) threadID += 1
 * 1) Create new threads

queueLock.acquire for word in nameList: workQueue.put(word) queueLock.release
 * 1) Fill the queue

while not workQueue.empty: pass
 * 1) Wait for queue to empty

exitFlag = 1
 * 1) Notify threads it's time to exit

for t in threads: t.join print "Exiting Main Thread" code || <span style="background-color: #ffffff; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: justify;">This would produce following result: code <span style="font-family: 'Courier New',monospace; font-size: 12px;">Starting Thread-2 Starting Thread-1 Starting Thread-3 Thread-2 processing One Thread-1 processing Two Thread-3 processing Three Thread-2 processing Four Thread-1 processing Five Exiting Thread-3 Exiting Thread-2 Exiting Thread-1 Exiting Main Thread code ||
 * 1) Wait for all threads to complete

<span style="background-color: #ffffff; color: #900b09; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;"> <span style="background-color: #ffffff; color: #900b09; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;"> <span style="background-color: #ffffff; color: #900b09; font-family: verdana,helvetica,arial,sans-serif; font-size: 11px; text-align: left;">