1. 程式人生 > 程式設計 >Python多執行緒模組Threading用法示例小結

Python多執行緒模組Threading用法示例小結

本文例項講述了Python多執行緒模組Threading用法。分享給大家供大家參考,具體如下:

步入正題前,先準備下基本知識,執行緒與程序的概念。

   相信作為一個測試人員,如果從理論概念上來說其兩者的概念或者區別,估計只會一臉矇蔽,這裡就舉個例子來說明下其中的相關概念。

  平安夜剛過,你是吃到了蘋果還是香蕉呢。。。其實當你用手去接下對方蘋果的時候,你的手臂就可以比喻成程序,你的五個手指就可以比喻成執行緒,所以很明顯,執行緒可以說是程序的細化,沒有程序就不會有執行緒。

   這裡還是說下必要的概念:

  程序

   是作業系統中當前程式的一次執行。要知道擁有單個CPU的電腦,在嚴格意義上,一個時間點上作業系統只能進行同一個工作命令。由於計算機的執行速度快,在工作時可以執行一會A程式碼,執行一會B程式碼,交錯執行,由於運算速度快,所以一般看來它好像可以同時進行多個程式--這就是多程序。

  執行緒

   執行緒是程式中一個單一的順序控制流程。程序內一個相對獨立的、可排程的執行單元,是系統獨立排程和分派CPU的基本單位,這裡的單位指執行中的程式的排程單位。在單個程式中同時執行多個執行緒完成不同的工作,稱為多執行緒。執行緒還可以自己建立、撤銷和切換。就像拿蘋果,如果一根手指可以辦到,那它就是單執行緒,如果需要多根手指,那就是多執行緒。

  程序和執行緒的區別

   (1)程序是資源的分配和排程的一個獨立單元,而執行緒是CPU排程的基本單元
(2)同一個程序中可以包括多個執行緒,並且執行緒共享整個程序的資源(暫存器、堆疊、上下文),一個程序至少包括一個執行緒。
(3)程序結束後它擁有的所有執行緒都將銷燬,而執行緒的結束不會影響同個程序中的其他執行緒的結束

(4)執行緒是輕量級的程序,它的建立和銷燬所需要的時間比程序小很多,所有作業系統中的執行功能都是建立執行緒去完成的
(5)執行緒中執行時一般都要進行同步和互斥,因為他們共享同一程序的所有資源(資源競爭)
(6)執行緒有自己的私有屬性TCB,執行緒id,暫存器、硬體上下文,而程序也有自己的私有屬性程序控制塊PCB,這些私有屬性是不被共享的,用來標示一個程序或一個執行緒的標誌

  子程序與子執行緒的區別

   程序和執行緒的區別在於粒度不同,程序之間的變數(或者說是記憶體)是不能直接互相訪問的,而執行緒可以,執行緒一定會依附在某一個程序上執行.我舉個例子,你在Windows下開一個IE瀏覽器,這個IE瀏覽器是一個程序. 你用瀏覽器去開啟一個pdf,IE就去呼叫Acrobat去開啟,這時Acrobat是一個獨立的程序,就是IE的子程序.而IE自己本身同時用同一個程序開了2個網頁,並且同時在跑兩個網頁上的指令碼,這兩個網頁的執行就是IE自己通過兩個執行緒實現的.值得注意的是,執行緒仍然是IE的內容,而子程序Acrobat嚴格來說就不屬於IE了,是另外一個程式,之所以是IE的子程序,只是受IE呼叫而啟動的而已。

   這裡大家可能會疑惑,程序分配記憶體空間的依據是啥?其實程序建立,系統會為其分配虛擬地址空間4GB(在32位系統中),具體分配情況要取決於該包含的所有可執行模組或dll模組的程式碼和資料,還包含動態記憶體分配的空間(如執行緒中堆疊的分配)

  好了,上面介紹了基本的執行緒及程序的概念,接下來可以開始正題了,這裡主要總結下python內的Threading模組

  python多執行緒之Threading

  單執行緒

  額,這個忽略吧。。。作業系統單任務的處理,排好隊,一個一個來就是單執行緒。

  多執行緒

  多執行緒Threading一般可以通過兩種渠道來實現:一種是通過繼承Thread類,重寫它的run方法;另一種是建立一個threading.Thread物件,在它的初始化函式(__init__)中將可呼叫物件作為引數傳入,本質上來講,兩種方式一樣。

  來一發例項:

# -*- coding: utf-8 -*-
import threading
import time
#方式二是方式一的具體,方式一為類構造,方式二為方法例項構造,其實本質都是一樣,都是呼叫threading.Thread模組
#方式一
count = 0
class Counter(threading.Thread):
  def __init__(self,lock,threadName):
    #注意:一定要顯式的呼叫父類的初始化函式,這裡可以指定生成的執行緒名,可以是*args、**kwargs
    #def __init__(self,group=None,target=None,name=None,args=(),kwargs={}),其中group是預留的,將來用於擴充套件
    super(Counter,self).__init__(name=threadName)
    self.lock = lock
  def run(self):
    global count
    self.lock.acquire()
    for i in range(100):
      count = count + 1
    self.lock.release()
#方式二
lockA = threading.Lock()
lockB = threading.Lock()
rLock = threading.RLock()
condt = threading.Condition()
event = threading.Event()
def add(lockA):
  global count
  #定義當前資源只能單執行緒訪問,鎖住後完成資源呼叫一定要釋放鎖,不然會造成死鎖狀態,甚至程式崩潰
  lockA.acquire()
  for i in range(1000):
    count = count + 1
  #資源呼叫完畢,釋放鎖
  lockA.release()
def addRunner():
  for i in range(2):
    th = threading.Thread(target=rloc,args=(rLock,))
    #開啟執行緒,從此刻起,多執行緒開始,主執行緒繼續前行
    th.start()
    #呼叫Thread.join[timeout]將會使主調執行緒堵塞,直到被呼叫執行緒執行結束或超時。引數timeout是一個數值型別,表示超時時間
    th.join()
    print '----- %s is start -----' % th.getName()
    print "over"
#RLock允許在同一執行緒中被多次acquire,避免單執行緒出現思索情況
def rloc(rLock):
  rLock.acquire()
  for i in range(2):
    rLock.acquire()
    print i,rLock.release()
  rLock.release()
  print "over!"
def rlocRun():
  for i in range(2):
    th = threading.Thread(target=rloc,))
    th.start()
    print '----- %s is start -----' % th.getName()
    print "over"
#現在出現複雜的場景,多個執行緒需要呼叫多個共同的資源,此時就需要threading.Condition出馬,加入簡單的說就是A搞完了A的事
# ,就發廣播說明自己搞定了,其它人可以進來了,B同理。
def cond(cond):
  #適合那種主動休眠,被動喚醒的場景
  cond.acquire()
  global count
  for i in range(1000):
    count = count + 1
  #喚醒一個掛起的執行緒(如果存在掛起的執行緒),提醒當前的掛起的執行緒看看其它的鎖開了沒有,如果開了就搞其他的事。
  #注意:notify()方法不會釋放所佔用的瑣。
  cond.notify()
  #wait方法釋放內部所佔用的瑣,同時執行緒被掛起,直至接收到通知被喚醒或超時
  cond.wait(5)
  #相信大家應該看出問題來了,最後一個執行緒咋辦列,沒人喚醒啊,這個時候應該做過一個判斷
  cond.release()
  print "over!"
def condRun():
  global condt
  for i in range(0,3):
    th = threading.Thread(target=cond,args=(condt,))
    th.start()
    print '----- %s is start -----' % th.getName()
  print "over"
#此時可能會有一點問題,就是執行緒的同步(併發)問題怎麼解決呢?此時threading.Event出馬
def even(n,event):
  while not event.isSet():
    print 'Thread %s is ready' % n
  time.sleep(1)
  #同condition一樣,掛起該執行緒,等待set開關
  event.wait()
  while event.isSet():
    print 'Thread %s is running' % n
    time.sleep(1)
def evenRun():
  for i in range(0,2):
    th = threading.Thread(target=even,args=(i,event))
    th.start()
  time.sleep(3)
  print '----- event is set -----'
  event.set()
  time.sleep(3)
  print '----- event is clear -----'
  event.clear()
if __name__ == "__main__":
  Counter(lockA,"thread1").start()
  addRunner()
  rlocRun()
  condRun()
  evenRun()

更多關於Python相關內容感興趣的讀者可檢視本站專題:《Python程序與執行緒操作技巧總結》、《Python資料結構與演算法教程》、《Python函式使用技巧總結》、《Python字串操作技巧彙總》、《Python入門與進階經典教程》、《Python+MySQL資料庫程式設計入門教程》及《Python常見資料庫操作技巧彙總》

希望本文所述對大家Python程式設計有所幫助。