Python Language Basics of multithreading


Example

Using the threading module, a new thread of execution may be started by creating a new threading.Thread and assigning it a function to execute:

import threading

def foo():
  print "Hello threading!"

my_thread = threading.Thread(target=foo)

The target parameter references the function (or callable object) to be run. The thread will not begin execution until start is called on the Thread object.

Starting a Thread

my_thread.start() # prints 'Hello threading!'

Now that my_thread has run and terminated, calling start again will produce a RuntimeError. If you'd like to run your thread as a daemon, passing the daemon=True kwarg, or setting my_thread.daemon to True before calling start(), causes your Thread to run silently in the background as a daemon.

Joining a Thread

In cases where you split up one big job into several small ones and want to run them concurrently, but need to wait for all of them to finish before continuing, Thread.join() is the method you're looking for.

For example, let's say you want to download several pages of a website and compile them into a single page. You'd do this:

import requests
from threading import Thread
from queue import Queue

q = Queue(maxsize=20)
def put_page_to_q(page_num):
    q.put(requests.get('http://some-website.com/page_%s.html' % page_num)

def compile(q):
    # magic function that needs all pages before being able to be executed
    if not q.full():
        raise ValueError
    else:
        print("Done compiling!")

threads = []
for page_num in range(20):
     t = Thread(target=requests.get, args=(page_num,))
     t.start()
     threads.append(t)

# Next, join all threads to make sure all threads are done running before
# we continue. join() is a blocking call (unless specified otherwise using 
# the kwarg blocking=False when calling join)
for t in threads:
    t.join()

# Call compile() now, since all threads have completed
compile(q)

A closer look at how join() works can be found here.

Create a Custom Thread Class

Using threading.Thread class we can subclass new custom Thread class. we must override run method in a subclass.

from threading import Thread
import time

class Sleepy(Thread):

    def run(self):
        time.sleep(5)
        print("Hello form Thread")

if __name__ == "__main__":
    t = Sleepy()
    t.start()      # start method automatic call Thread class run method.
    # print 'The main program continues to run in foreground.'
    t.join()
    print("The main program continues to run in the foreground.")