python多執行緒之從Thread類繼承

dwzb發表於2019-02-27

本文首發於知乎

上一篇文章實現多執行緒的方式是

  • 建立函式
  • 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程式設計

專欄目錄:目錄

版本說明:軟體及包版本說明

相關文章