Python 多線程 threading和multiprocessing模塊

Python 多線程 threading和multiprocessing模塊

Python中常使用的線程模塊

thread(低版本使用的),threading
Queue
multiprocessing
threading

thread模塊是Python低版本中使用的,高版本中被threading代替了。threading模塊提供了更方便的API來(lái)操作線程。

threading.Thread

Thread是threading模塊中最重要的類之一,可以使用它來(lái)創(chuàng)建線程。創(chuàng)建新的線程有兩種方法:

方法一:直接創(chuàng)建threading.Thread類的對(duì)象,初始化時(shí)將可調(diào)用對(duì)象作為參數(shù)傳入。
方法二:通過(guò)繼承Thread類,重寫它的run方法。

Thread類的構(gòu)造方法:

__init__(group=None, target=None, name=None, args=(), kwargs=None, verbose=None)

參數(shù)說(shuō)明:

group:線程組,目前還沒(méi)有實(shí)現(xiàn),庫(kù)引用中提示必須是None。
target:要執(zhí)行的方法;
name:線程名;
args/kwargs:要傳入方法的參數(shù)。

Thread類擁有的實(shí)例方法:

isAlive():返回線程是否在運(yùn)行。正在運(yùn)行指的是啟動(dòng)后,終止前。

getName(name)/setName(name):獲取/設(shè)置線程名。

isDaemon(bool)/setDaemon(bool):獲取/設(shè)置是否為守護(hù)線程。初始值從創(chuàng)建該線程的線程繼承而來(lái),當(dāng)沒(méi)有非守護(hù)線程仍在運(yùn)行時(shí),程序?qū)⒔K止。

start():?jiǎn)?dòng)線程。

join([timeout]):阻塞當(dāng)前上下文環(huán)境的線程,直到調(diào)用此方法的線程終止或到達(dá)指定的等待時(shí)間timeout(可選參數(shù))。即當(dāng)前的線程要等調(diào)用join()這個(gè)方法的線程執(zhí)行完,或者是達(dá)到規(guī)定的時(shí)間。

直接創(chuàng)建threading.Thread類的對(duì)象

實(shí)例:

from threading import Thread
import time
def run(a = None, b = None) :
  print a, b
  time.sleep(1)

t = Thread(target = run, args = ("this is a", "thread"))
#此時(shí)線程是新建狀態(tài)

print t.getName()#獲得線程對(duì)象名稱
print t.isAlive()#判斷線程是否還活著。
t.start()#啟動(dòng)線程
t.join()#等待其他線程運(yùn)行結(jié)束

執(zhí)行結(jié)果:

Thread-1
False
this is a thread
1
2
3
4
1
2
3
4

注意:

t = Thread(target = run, args = ("this is a", "thread"))
這句只是創(chuàng)建了一個(gè)線程,并未執(zhí)行這個(gè)線程,此時(shí)線程處于新建狀態(tài)。
t.start()#啟動(dòng)線程
啟動(dòng)線程,此時(shí)線程扔為運(yùn)行,只是處于準(zhǔn)備狀態(tài)。

自定義函數(shù)run(),使我們自己根據(jù)我們需求自己定義的,函數(shù)名可以隨便取,run函數(shù)的參數(shù)來(lái)源于后面的args元組。

通過(guò)繼承Thread類

實(shí)例:

from threading import Thread
import time

class MyThread(Thread) :
  def __init__(self, a) :
    super(MyThread, self).__init__()
    #調(diào)用父類的構(gòu)造方法
    self.a = a

  def run(self) :
    print "sleep :", self.a
    time.sleep(self.a)

t1 = MyThread(2)
t2 = MyThread(4)
t1.start()
t2.start()
t1.join()
t2.join()

執(zhí)行結(jié)果:

4

由于創(chuàng)建了兩個(gè)并發(fā)執(zhí)行的線程t1和t2,并發(fā)線程的執(zhí)行時(shí)間不定,誰(shuí)先執(zhí)行完的時(shí)間也不定,所以執(zhí)行后打印的結(jié)果順序也是不定的。每一次執(zhí)行都有可能出現(xiàn)不同的結(jié)果。

注意:

繼承Thread類的新類MyThread構(gòu)造函數(shù)中必須要調(diào)用父類的構(gòu)造方法,這樣才能產(chǎn)生父類的構(gòu)造函數(shù)中的參數(shù),才能產(chǎn)生線程所需要的參數(shù)。新的類中如果需要?jiǎng)e的參數(shù),直接在其構(gòu)造方法中加即可。
同時(shí),新類中,在重寫父類的run方法時(shí),它默認(rèn)是不帶參數(shù)的,如果需要給它提供參數(shù),需要在類的構(gòu)造函數(shù)中指定,因?yàn)樵诰€程執(zhí)行的過(guò)程中,run方法時(shí)線程自己去調(diào)用的,不用我們手動(dòng)調(diào)用,所以沒(méi)法直接給傳遞參數(shù),只能在構(gòu)造方法中設(shè)定好參數(shù),然后再run方法中調(diào)用。

針對(duì)join()函數(shù)用法的實(shí)例:

# encoding: UTF-8
import threading
import time

def context(tJoin):
    print 'in threadContext.'
    tJoin.start()
    # 將阻塞tContext直到threadJoin終止。
    tJoin.join()
    # tJoin終止后繼續(xù)執(zhí)行。
    print 'out threadContext.'

def join():
    print 'in threadJoin.'
    time.sleep(1)
    print 'out threadJoin.'

tJoin = threading.Thread(target=join)
tContext = threading.Thread(target=context, args=(tJoin,))
tContext.start()

執(zhí)行結(jié)果:

in threadContext.
in threadJoin.
out threadJoin.
out threadContext.
1
2
3
4
5
1
2
3
4
5

解析:

主程序中這句tJoin = threading.Thread(target=join)執(zhí)行后,只是創(chuàng)建了一個(gè)線程對(duì)象tJoin,但并未啟動(dòng)該線程。

tContext = threading.Thread(target=context, args=(tJoin,))
tContext.start()

上面這兩句執(zhí)行后,創(chuàng)建了另一個(gè)線程對(duì)象tContext并啟動(dòng)該線程(打印in threadContext.),同時(shí)將tJoin線程對(duì)象作為參數(shù)傳給context函數(shù),在context函數(shù)中,啟動(dòng)了tJoin這個(gè)線程,同時(shí)該線程又調(diào)用了join()函數(shù)(tJoin.join()),那tContext線程將等待tJoin這線程執(zhí)行完成后,才能繼續(xù)tContext線程后面的,所以先執(zhí)行join()函數(shù),打印輸出下面兩句:

in threadJoin.
out threadJoin.

tJoin線程執(zhí)行結(jié)束后,繼續(xù)執(zhí)行tContext線程,于是打印輸出了out threadContext.,于是就看到我們上面看到的輸出結(jié)果,并且無(wú)論執(zhí)行多少次,結(jié)果都是這個(gè)順序。但如果將context()函數(shù)中tJoin.join()這句注釋掉,再執(zhí)行該程序,打印輸出的結(jié)果順序就不定了,因?yàn)榇藭r(shí)這兩線程就是并發(fā)執(zhí)行的。

multiprocessing.dummy

Python中線程multiprocessing模塊與進(jìn)程使用的同一模塊。使用方法也基本相同,唯一不同的是,from multiprocessing import Pool這樣導(dǎo)入的Pool表示的是進(jìn)程池;
from multiprocessing.dummy import Pool這樣導(dǎo)入的Pool表示的是線程池。這樣就可以實(shí)現(xiàn)線程里面的并發(fā)了。

線程池實(shí)例:

import time
from multiprocessing.dummy import Pool as ThreadPool
#給線程池取一個(gè)別名ThreadPool
def run(fn):
  time.sleep(2)
  print fn

if __name__ == '__main__':
  testFL = [1,2,3,4,5]
  pool = ThreadPool(10)#創(chuàng)建10個(gè)容量的線程池并發(fā)執(zhí)行
  pool.map(run, testFL)
  pool.close()
  pool.join()

執(zhí)行結(jié)果:

5

這里的pool.map()函數(shù),跟進(jìn)程池的map函數(shù)用法一樣,也跟內(nèi)建的map函數(shù)一樣。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 線程 1.同步概念 1.多線程開發(fā)可能遇到的問(wèn)題 同步不是一起的意思,是協(xié)同步調(diào) 假設(shè)兩個(gè)線程t1和t2都要對(duì)nu...
    TENG書閱讀 697評(píng)論 0 1
  • 本文是筆者學(xué)習(xí)廖雪峰Python3教程的筆記,在此感謝廖老師的教程讓我們這些初學(xué)者能夠一步一步的進(jìn)行下去.如果讀者...
    相關(guān)函數(shù)閱讀 5,611評(píng)論 1 8
  • 1.進(jìn)程和線程 隊(duì)列:1、進(jìn)程之間的通信: q = multiprocessing.Queue()2、...
    一只寫程序的猿閱讀 1,242評(píng)論 0 17
  • 多任務(wù)可以由多進(jìn)程完成,也可以由一個(gè)進(jìn)程內(nèi)的多線程完成。我們前面提到了進(jìn)程是由若干線程組成的,一個(gè)進(jìn)程至少有一個(gè)線...
    壁花燒年閱讀 885評(píng)論 0 0
  • 最近有一位久不聯(lián)系的老朋友突然聊了起來(lái),他說(shuō)他遇到了好多事,一度比較苦惱,難以解脫出來(lái)。作為曾經(jīng)形影不離的好...
    悟心醫(yī)舊閱讀 341評(píng)論 0 0

友情鏈接更多精彩內(nèi)容