多執行緒基礎知識

使用 threading 模組,可以通過建立新的 threading.Thread 併為其分配執行的函式來啟動新的執行執行緒:

import threading

def foo():
  print "Hello threading!"

my_thread = threading.Thread(target=foo)

target 引數引用要執行的函式(或可呼叫物件)。在 Thread 物件上呼叫 start 之前,執行緒不會開始執行。

開始一個執行緒

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

現在 my_thread 已經執行並終止,再次呼叫 start 會產生一個 RuntimeError。如果你想將你的執行緒作為一個守護程序執行,傳遞 daemon=True kwarg,或者在呼叫 start() 之前將 my_thread.daemon 設定為 True,會導致你的 Thread 作為守護程序在後臺靜默執行。

加入主題

如果你將一個大工作分成幾個小工作並想要同時執行它們,但需要等待所有這些工作完成才能繼續,Thread.join() 是你正在尋找的方法。

例如,假設你要下載網站的多個頁面並將其編譯為單個頁面。你這樣做:

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)

仔細看看 join() 如何工作可以在這裡找到。

建立自定義執行緒類

使用 threading.Thread 類我們可以繼承新的自定義 Thread 類。我們必須在子類中覆蓋 run 方法。

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.")