本文首發於知乎
上一篇文章實現多執行緒的方式是
- 建立函式
- 用
Thread
函式建立程式,將要執行的函式傳入其中
本文我們講另一種實現多執行緒的方式————從threading.Thread類繼承出一個新類,主要實現__init__
和run
方法
一
首先我們來看一個最簡單的例子,只實現了run
方法
import time
import threading
class MyThread(threading.Thread):
def run(self):
time.sleep(1)
a = 1 + 1
print(a)
for _ in range(5):
th = MyThread()
th.start()
複製程式碼
總結一下
- 定義一個類,繼承
threading.Thread
類,裡面只需要定義run
方法 run
方法相當於之前傳入Thread
的那個函式,注意只能用run
這個名字,不用顯式呼叫,執行緒start()
時會自動呼叫run
- 建立類的例項時不需要傳入引數,得到的結果就可以呼叫
start join
等方法 - 上一篇文章提過
Thread
物件可以呼叫start join run
等方法,其實當時呼叫start
就自動呼叫了run
。這裡只不過是在新類中重寫了run
方法,執行緒呼叫start
時就會自動執行這個run
二
上面每次執行的run
都是一樣的,真正使用時很少會這樣用,有時會需要傳入一些區別性的引數,這就需要定義類的__init__
了,我們來看下面的例子
import threading
import requests
from bs4 import BeautifulSoup
class MyThread(threading.Thread):
def __init__(self, i):
threading.Thread.__init__(self)
self.i = i
def run(self):
url = `https://movie.douban.com/top250?start={}&filter=`.format(self.i*25)
r = requests.get(url)
soup = BeautifulSoup(r.content, `html.parser`)
lis = soup.find(`ol`, class_=`grid_view`).find_all(`li`)
for li in lis:
title = li.find(`span`, class_="title").text
print(title)
for i in range(10):
th = MyThread(i)
th.start()
複製程式碼
上面程式碼實現10個執行緒抓取豆瓣top250網站10頁的電影名,通過__init__
將迴圈資訊傳到類之中。
三
上一篇文章不使用類來使用多執行緒時,講了Thread
函式的引數,Thread
物件的方法和一些可以直接呼叫的變數,這裡我們分別講一下
Thread
函式的引數。初始化執行緒時傳入一些引數,這裡也可以在__init__
中定義Thread
物件的方法。這裡可以用self
直接呼叫這些方法threading.activeCount()
等直接呼叫的變數。在這裡依然可以呼叫
所以用類的方法不會有任何限制,下面來看一個使用的例子
import time
import threading
class MyThread(threading.Thread):
def __init__(self, name):
threading.Thread.__init__(self)
self.name = name
def run(self):
a = 1 + 1
print(threading.currentThread().name)
time.sleep(1)
print(self.name)
time.sleep(1)
print(self.is_alive())
t = time.time()
ths = [MyThread(`thread {}`.format(i)) for i in range(3)]
for th in ths:
th.start()
print(threading.activeCount())
for th in ths:
th.join()
print(time.time() - t)
複製程式碼
返回結果如下
thread 0
thread 1
thread 2
4
thread 0
thread 2
thread 1
True
True
True
2.0039498805999756
複製程式碼
四
使用類繼承方式其實還有另一種形式。
之前是直接用run
定義計算函式,如果已經有一個計算函式,也可以用傳入的方式而不是改寫成run
import threading
import requests
from bs4 import BeautifulSoup
def gettitle(page):
url = `https://movie.douban.com/top250?start={}&filter=`.format(page*25)
r = requests.get(url)
soup = BeautifulSoup(r.content, `html.parser`)
lis = soup.find(`ol`, class_=`grid_view`).find_all(`li`)
for li in lis:
title = li.find(`span`, class_="title").text
print(title)
class MyThread(threading.Thread):
def __init__(self, target, **args):
threading.Thread.__init__(self)
self.target = target
self.args = args
def run(self):
self.target(**self.args)
for i in range(10):
th = MyThread(gettitle, page = i)
th.start()
複製程式碼
歡迎關注我的知乎專欄
專欄主頁:python程式設計
專欄目錄:目錄
版本說明:軟體及包版本說明