多线程基础知识
使用 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.")