溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Python中Thread線程模塊是什么

發(fā)布時間:2020-08-04 14:55:17 來源:億速云 閱讀:138 作者:清晨 欄目:編程語言

這篇文章將為大家詳細(xì)講解有關(guān)Python中Thread線程模塊是什么,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

threading.Thread

Thread 是threading模塊中最重要的類之一,可以使用它來創(chuàng)建線程。有兩種方式來創(chuàng)建線程:一種是通過繼承Thread類,重寫它的run方法;另一種是創(chuàng)建一個threading.Thread對象,在它的初始化函數(shù)(__init__)中將可調(diào)用對象作為參數(shù)傳入。下面分別舉例說明。

Python中Thread線程模塊是什么

先來看看通過繼承threading.Thread類來創(chuàng)建線程的例子:

#coding=gbk
import threading, time, random
count = 0
class Counter(threading.Thread):
  def __init__(self, lock, threadName):
'''@summary: 初始化對象。
@param lock: 瑣對象。
@param threadName: 線程名稱。
'''
    super(Counter, self).__init__(name = threadName) 
#注意:一定要顯式的調(diào)用父類的初始化函數(shù)。
    self.lock = lock
  def run(self):
'''@summary: 重寫父類run方法,在線程啟動后執(zhí)行該方法內(nèi)的代碼。
'''
    global count
    self.lock.acquire()
    for i in xrange(10000):
      count = count + 1
    self.lock.release()
lock = threading.Lock()
for i in range(5): 
  Counter(lock, "thread-" + str(i)).start()
time.sleep(2)  
#確保線程都執(zhí)行完畢
print count

在代碼中,我們創(chuàng)建了一個Counter類,它繼承了threading.Thread。初始化函數(shù)接收兩個參數(shù),一個是瑣對象,另一個是線程的名稱。在Counter中,重寫了從父類繼承的run方法,run方法將一個全局變量逐一的增加10000。

在接下來的代碼中,創(chuàng)建了五個Counter對象,分別調(diào)用其start方法。最后打印結(jié)果。這里要說明一下run方法 和start方法: 它們都是從Thread繼承而來的,run()方法將在線程開啟后執(zhí)行,可以把相關(guān)的邏輯寫到run方法中(通常把run方法稱為活動[Activity]。);start()方法用于啟動線程。

再看看另外一種創(chuàng)建線程的方法:

import threading, time, random
count = 0
lock = threading.Lock()
def doAdd():
'''@summary: 將全局變量count 逐一的增加10000。
'''
  global count, lock
  lock.acquire()
  for i in xrange(10000):
    count = count + 1
  lock.release()
for i in range(5):
  threading.Thread(target = doAdd, args = (), name = 'thread-' + str(i)).start()
time.sleep(2)  
#確保線程都執(zhí)行完畢
print count

在這段代碼中,我們定義了方法doAdd,它將全局變量count 逐一的增加10000。然后創(chuàng)建了5個Thread對象,把函數(shù)對象doAdd 作為參數(shù)傳給它的初始化函數(shù),再調(diào)用Thread對象的start方法,線程啟動后將執(zhí)行doAdd函數(shù)。這里有必要介紹一下threading.Thread類的初始化函數(shù)原型:

def __init__(self, group=None, target=None, name=None, args=(), kwargs={})

  參數(shù)group是預(yù)留的,用于將來擴展;

  參數(shù)target是一個可調(diào)用對象(也稱為活動[activity]),在線程啟動后執(zhí)行;

  參數(shù)name是線程的名字。默認(rèn)值為“Thread-N“,N是一個數(shù)字。

  參數(shù)args和kwargs分別表示調(diào)用target時的參數(shù)列表和關(guān)鍵字參數(shù)。

Thread類還定義了以下常用方法與屬性:

Thread.getName()
Thread.setName()
Thread.name

用于獲取和設(shè)置線程的名稱。

Thread.ident

獲取線程的標(biāo)識符。線程標(biāo)識符是一個非零整數(shù),只有在調(diào)用了start()方法之后該屬性才有效,否則它只返回None。

Thread.is_alive()

Thread.isAlive()

判斷線程是否是激活的(alive)。從調(diào)用start()方法啟動線程,到run()方法執(zhí)行完畢或遇到未處理異常而中斷 這段時間內(nèi),線程是激活的。

Thread.join([timeout])

調(diào)用Thread.join將會使主調(diào)線程堵塞,直到被調(diào)用線程運行結(jié)束或超時。參數(shù)timeout是一個數(shù)值類型,表示超時時間,如果未提供該參數(shù),那么主調(diào)線程將一直堵塞到被調(diào)線程結(jié)束。下面舉個例子說明join()的使用:

import threading, time
def doWaiting():
  print 'start waiting:', time.strftime('%H:%M:%S')
  time.sleep(3)
  print 'stop waiting', time.strftime('%H:%M:%S')
thread1 = threading.Thread(target = doWaiting)
thread1.start()
time.sleep(1) 
#確保線程thread1已經(jīng)啟動
print 'start join'
thread1.join() 
#將一直堵塞,直到thread1運行結(jié)束。
print 'end join'
threading.RLock和threading.Lock

在threading模塊中,定義兩種類型的瑣:threading.Lock和threading.RLock。它們之間有一點細(xì)微的區(qū)別,通過比較下面兩段代碼來說明:

import threading
lock = threading.Lock() 
#Lock對象
lock.acquire()
lock.acquire() 
#產(chǎn)生了死瑣。
lock.release()
lock.release()
import threading
rLock = threading.RLock() 
#RLock對象
rLock.acquire()
rLock.acquire() 
#在同一線程內(nèi),程序不會堵塞。
rLock.release()
rLock.release()

這兩種瑣的主要區(qū)別是:RLock允許在同一線程中被多次acquire。而Lock卻不允許這種情況。注意:如果使用RLock,那么acquire和release必須成對出現(xiàn),即調(diào)用了n次acquire,必須調(diào)用n次的release才能真正釋放所占用的瑣。

threading.Condition

可以把Condiftion理解為一把高級的瑣,它提供了比Lock, RLock更高級的功能,允許我們能夠控制復(fù)雜的線程同步問題。threadiong.Condition在內(nèi)部維護(hù)一個瑣對象(默認(rèn)是RLock),可以在創(chuàng)建Condigtion對象的時候把瑣對象作為參數(shù)傳入。Condition也提供了acquire, release方法,其含義與瑣的acquire, release方法一致,其實它只是簡單的調(diào)用內(nèi)部瑣對象的對應(yīng)的方法而已。Condition還提供了如下方法(特別要注意:這些方法只有在占用瑣(acquire)之后才能調(diào)用,否則將會報RuntimeError異常。):

Condition.wait([timeout]):

wait方法釋放內(nèi)部所占用的瑣,同時線程被掛起,直至接收到通知被喚醒或超時(如果提供了timeout參數(shù)的話)。當(dāng)線程被喚醒并重新占有瑣的時候,程序才會繼續(xù)執(zhí)行下去。

Condition.notify():

喚醒一個掛起的線程(如果存在掛起的線程)。注意:notify()方法不會釋放所占用的瑣。

Condition.notify_all()

Condition.notifyAll()

喚醒所有掛起的線程(如果存在掛起的線程)。注意:這些方法不會釋放所占用的瑣。

現(xiàn)在寫個捉迷藏的游戲來具體介紹threading.Condition的基本使用。假設(shè)這個游戲由兩個人來玩,一個藏(Hider),一個找(Seeker)。游戲的規(guī)則如下:1. 游戲開始之后,Seeker先把自己眼睛蒙上,蒙上眼睛后,就通知Hider;2. Hider接收通知后開始找地方將自己藏起來,藏好之后,再通知Seeker可以找了; 3. Seeker接收到通知之后,就開始找Hider。Hider和Seeker都是獨立的個體,在程序中用兩個獨立的線程來表示,在游戲過程中,兩者之間的行為有一定的時序關(guān)系,我們通過Condition來控制這種時序關(guān)系。

#---- Condition
#---- 捉迷藏的游戲
import threading, time
class Hider(threading.Thread):
  def __init__(self, cond, name):
    super(Hider, self).__init__()
    self.cond = cond
    self.name = name
  def run(self):
    time.sleep(1) 
#確保先運行Seeker中的方法  
      
    self.cond.acquire() 
#b  
    print self.name + ': 我已經(jīng)把眼睛蒙上了'
    self.cond.notify()
    self.cond.wait() 
#c  
              
#f 
    print self.name + ': 我找到你了 ~_~'
    self.cond.notify()
    self.cond.release()
               
#g
    print self.name + ': 我贏了' 
#h
      
class Seeker(threading.Thread):
  def __init__(self, cond, name):
    super(Seeker, self).__init__()
    self.cond = cond
    self.name = name
  def run(self):
    self.cond.acquire()
    self.cond.wait()  
#a  #釋放對瑣的占用,同時線程掛起在這里,直到被notify并重新占
有瑣。
               
#d
    print self.name + ': 我已經(jīng)藏好了,你快來找我吧'
    self.cond.notify()
    self.cond.wait()  
#e
               
#h
    self.cond.release() 
    print self.name + ': 被你找到了,哎~~~'
      
cond = threading.Condition()
seeker = Seeker(cond, 'seeker')
hider = Hider(cond, 'hider')
seeker.start()
hider.start()

threading.Event

Event實現(xiàn)與Condition類似的功能,不過比Condition簡單一點。它通過維護(hù)內(nèi)部的標(biāo)識符來實現(xiàn)線程間的同步問題。(threading.Event和.NET中的System.Threading.ManualResetEvent類實現(xiàn)同樣的功能。)

Event.wait([timeout])

堵塞線程,直到Event對象內(nèi)部標(biāo)識位被設(shè)為True或超時(如果提供了參數(shù)timeout)。

Event.set()

將標(biāo)識位設(shè)為Ture

Event.clear()

將標(biāo)識伴設(shè)為False。

Event.isSet()

判斷標(biāo)識位是否為Ture。

下面使用Event來實現(xiàn)捉迷藏的游戲(可能用Event來實現(xiàn)不是很形象)

#---- Event
#---- 捉迷藏的游戲
import threading, time
class Hider(threading.Thread):
  def __init__(self, cond, name):
    super(Hider, self).__init__()
    self.cond = cond
    self.name = name
  def run(self):
    time.sleep(1) 
#確保先運行Seeker中的方法  
    print self.name + ': 我已經(jīng)把眼睛蒙上了'
    self.cond.set()
    time.sleep(1)  
    self.cond.wait()
    print self.name + ': 我找到你了 ~_~'
    self.cond.set()     
    print self.name + ': 我贏了'
class Seeker(threading.Thread):
  def __init__(self, cond, name):
    super(Seeker, self).__init__()
    self.cond = cond
    self.name = name
  def run(self):
    self.cond.wait()
    print self.name + ': 我已經(jīng)藏好了,你快來找我吧'
    self.cond.set()
    time.sleep(1)
    self.cond.wait()
    print self.name + ': 被你找到了,哎~~~'
cond = threading.Event()
seeker = Seeker(cond, 'seeker')
hider = Hider(cond, 'hider')
seeker.start()
hider.start()

threading.Timer

threading.Timer是threading.Thread的子類,可以在指定時間間隔后執(zhí)行某個操作。下面是Python手冊上提供的一個例子:

def hello():
  print "hello, world"
t = Timer(3, hello)
t.start() 
# 3秒鐘之后執(zhí)行hello函數(shù)。

threading模塊中還有一些常用的方法沒有介紹:

threading.active_count()

threading.activeCount()

獲取當(dāng)前活動的(alive)線程的個數(shù)。

threading.current_thread()

threading.currentThread()

獲取當(dāng)前的線程對象(Thread object)。

threading.enumerate()

獲取當(dāng)前所有活動線程的列表。

threading.settrace(func)

設(shè)置一個跟蹤函數(shù),用于在run()執(zhí)行之前被調(diào)用。

threading.setprofile(func)

設(shè)置一個跟蹤函數(shù),用于在run()執(zhí)行完畢之后調(diào)用。

threading模塊的內(nèi)容很多。

關(guān)于Python中Thread線程模塊是什么就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI