python多線程開發(fā)

Python的線程開發(fā)使用標(biāo)準(zhǔn)庫(kù)threading

目前成都創(chuàng)新互聯(lián)已為近1000家的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管、網(wǎng)站托管、企業(yè)網(wǎng)站設(shè)計(jì)、臨汾網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。

Thread類

def  __init__(self,group=None,target=None,name=None,args(),kwargs=None,*,daemon=None)
        參數(shù)名                     含義
        target線程調(diào)用的對(duì)象,就是目標(biāo)函數(shù)
        name為線程起的名字
        args為目標(biāo)函數(shù)傳遞實(shí)參,元組
       kwargs為目標(biāo)函數(shù)傳遞關(guān)鍵字參數(shù),字典

線程啟動(dòng)

import threading 

def worker():
    print("I'm working! wait a moment")
    
t=threading.Thread(target=worker,name='worker')   # 線程對(duì)象
t.start().                                        # 啟動(dòng)

       通過(guò)threading.Thread創(chuàng)建一個(gè)線程對(duì)象,target是目標(biāo)函數(shù),name可以指定自己喜歡的名字,線程的啟動(dòng)需要借助start方法。線程執(zhí)行函數(shù),是因?yàn)榫€程中就是執(zhí)行代碼的,最簡(jiǎn)單的封裝就是函數(shù),所以本質(zhì)還是函數(shù)調(diào)用。

線程退出

Python沒(méi)有提供線程的退出方法,線程在下面的情況下時(shí)會(huì)退出

    1. 線程函數(shù)內(nèi)語(yǔ)句執(zhí)行完畢

    2. 線程函數(shù)中拋出未處理的異常

import  threading 
import  time 

def worker( ):
  count=0
  while True:
      if(count>5):
        raise RuntimeError(count)
      time.sleep(1)
    print("I'm  working!")
    count+=1
        
t=threading.Thread(target=worker,name="worker")
t.start( )
print("===End===")

結(jié)果如圖所示:

python多線程開發(fā)

Python的線程沒(méi)有優(yōu)先級(jí),沒(méi)有線程組的概念。

線程的傳參

import   threading 
import   time 

def add(x,y):
    print("{} + {} = {}".format(x,y,x+y))
    
t1=threading.Thread(target=add,name="add",args(4,5))
t1.start()
time.sleep(2)

t2=threading.Thread(target=add,name="add",kwargs={"x":4;"y":5})
t2.start()
time.sleep(2)

t3=threading.Thread(target=add,name="add",args=(4,),kwargs={"y":5})
t3.start()

線程傳參和函數(shù)傳參沒(méi)什么區(qū)別,本質(zhì)上就是函數(shù)傳參。

threading的屬性和方法

              名稱                         含義
    current_thread( )返回當(dāng)前線程對(duì)象
    main_thread( )返回主線程對(duì)象
    active_count( )當(dāng)前處于alive狀態(tài)的線程個(gè)數(shù)
    enumerate( )返回所有活著的線程的列表,不包括已經(jīng)終止的線程和未開始的線程
    get_ident( )返回當(dāng)前線程的ID,非0整數(shù)

import   threading
import   time 

def showthreadinfo():
  print("currentthread = {}".format(threading.current_thread()))
  print("main thread = {}".format(threading.main_thread()))
  print("active count = {}".format(threading.active_count()))
    
def worker():
  count=0
  showthreadinfo()
  while True:
      if(count>5):
          break
      time.sleep(1)
    count+=1
    print("I'm working")
        
t=threading.Thread(target=worker,name='worker')
t.start()
print('===End===')

結(jié)果如圖所示:

python多線程開發(fā)

Thread實(shí)例的屬性和方法

名稱含義
name只是一個(gè)名字,可以重新命名。getName(),setName()獲取,設(shè)置這個(gè)名詞
ident線程ID,它是非0整數(shù),線程啟動(dòng)后才會(huì)有ID,線程退出,仍可以訪問(wèn),可重復(fù)使用
is_alive()返回線程是否存活

多線程

一個(gè)進(jìn)程中如果有多個(gè)線程,就是多線程,實(shí)現(xiàn)一種并發(fā)

import   threading
import   time 

def worker():
  count=0
  while True:
      if(count>5):
        break
    time.sleep(0.5)
    count+=1
    print("worker running")
    print(threading.current_thread().name,threading.current_thread().ident)
 
t1=threading.Thread(name="worker1",target=worker)
t2=threading.Thread(name="worker2",target=worker)
 
t1.start()
t2.start()

結(jié)果如圖所示:

python多線程開發(fā)

可以看到worker1和worker2交替執(zhí)行

daemon線程和non-daemon線程

進(jìn)程靠線程執(zhí)行代碼,至少有一個(gè)主線程,其它的線程都是工作線程。

父線程:如果線程A中啟動(dòng)了一個(gè)線程B,A就是B的父線程。

子線程:B就是A的子線程。

       Python中,構(gòu)造線程的時(shí)候,可以設(shè)置daemon屬性,這個(gè)屬性必須在start方法之前設(shè)置好。線程daemon屬性,如果設(shè)定就是用戶的設(shè)置,否則就取當(dāng)前線程的daemon值,主線程是non-daemon線程,即daemon=False

import time 
import threading 

def foo():
    time.sleep(3)
  for i in range(10):
      print(i)
        
t=threading.Thread(target=foo,daemon=False)
t.start()
print("Main Thread Exiting")

運(yùn)行結(jié)果如圖所示:

python多線程開發(fā)

        主進(jìn)程已經(jīng)執(zhí)行完畢,但是線程t依然在運(yùn)行,主進(jìn)程一直等待著線程t。當(dāng)將Thread中daemon=False改為True時(shí)發(fā)現(xiàn),主進(jìn)程執(zhí)行后立即會(huì)結(jié)束,根本不會(huì)等待t線程。

名稱含義
daemon屬性表示線程是否是daemon線程,這個(gè)值必須在start之前設(shè)置,否則引發(fā)RuntimeError異常
isDaemon是否是Daemon線程
setDaemon設(shè)置為daemon線程,必須在start方法之前設(shè)置

總結(jié):

       線程具有一個(gè)daemon屬性,可以設(shè)置主進(jìn)程結(jié)束后是否等待其他的子線程,如果不設(shè)置,取默認(rèn)值None。從主線程創(chuàng)建的所有線程的不設(shè)置daemon屬性,則默認(rèn)daemon=False。

join方法

import   time 
import   threading

def foo(n):
    for i in range(10):
        print(i)
        time.sleep(1)
       
t1=threading.Thread(target=foo,args=(10,),daemon=True)
t1.start()
t1.join()

執(zhí)行結(jié)果如圖所示:

python多線程開發(fā)

      根據(jù)上面講述的daemon線程,主進(jìn)程設(shè)置的dameon=True,按理說(shuō)主線程執(zhí)行是根本不會(huì)去等待其它的線程,也就是不會(huì)打印這些數(shù)字,但是這里卻等待了子線程的運(yùn)行打印出來(lái)了,這個(gè)就是join方法的作用。

       join(timeout=None),是線程標(biāo)準(zhǔn)方法之一,一個(gè)線程中調(diào)用另一個(gè)線程的join方法,調(diào)用者將被阻塞,直到被調(diào)用的線程停止。一個(gè)線程可以被join多次,timeout是設(shè)置等待調(diào)用者多久,如果沒(méi)有設(shè)置,就一直等待,直到被調(diào)用者線程結(jié)束。

threading.local類

      Python提供了threading.local類,將這個(gè)類實(shí)例化得到一個(gè)全局對(duì)象,但是不同的線程使用這個(gè)對(duì)象存儲(chǔ)的數(shù)據(jù)其他線程是不可見的。

import  threading
import  time 

#全局對(duì)象
global_data=threading.local()

def worker():
    global_data=0
    for i in range(100):
        time.sleep(0.001)
        global_data+=1
    print(threading.current_thread(),global_data)
    
for i  in range(10):
    threading.Thread(target=worker).start()

運(yùn)行結(jié)果如圖所示:

python多線程開發(fā)

     可以看到雖然是全局變量,但是這個(gè)變量在各個(gè)線程之間是獨(dú)立的,每個(gè)的計(jì)算結(jié)果不會(huì)對(duì)其他線程造成干擾。

     怎么證明這個(gè)是在各個(gè)線程之間獨(dú)立的呢?

import   threading 

TestData="abc"
TestLocal=threading.local()
TestLocal.x=123

print(TestData,type(TestLocal),TestLocal.x)

def worker():
    print(TestData)
    print(TestLocal)
    print(TestLocal.x)
    
worker()
print("=====")
threading.Thread(target=worker).start()

可以看下運(yùn)行結(jié)果

python多線程開發(fā)

       在子線程里面打印TestLocal.x時(shí)候出錯(cuò),顯示AttributeError: "_thread._local_" object has no attribute 'x',這是因?yàn)門estLocal.x我們是在主線程里面定義的,啟動(dòng)一個(gè)子線程我們并沒(méi)有這個(gè)屬性,所以報(bào)錯(cuò),從而說(shuō)明threading.local定義的變量,在各個(gè)線程之間是獨(dú)立的,不能跨線程。

       threading.local類構(gòu)建了一個(gè)大字典,其元素是每一線程實(shí)例的地址為key和線程對(duì)象引用線程單獨(dú)的字典的映射:

                              {id(Thread) ->  (ref(Thread), thread-local dict)}

    

 定時(shí)器Timer

       threading.Timer繼承自Thread,用來(lái)定義多久執(zhí)行一個(gè)函數(shù)。

class  threading.Timer(interval,function,args=None,kwargs=None)

       start方法執(zhí)行之后,Timer對(duì)象會(huì)等待interval時(shí)間,然后開始執(zhí)行function函數(shù),如果在等待階段,使用了cancal方法,就會(huì)跳過(guò)執(zhí)行而結(jié)束

import   threading 
import   time 

def worker():
    print("in worker")
    time.sleep(2)
    
t=threading.Timer(5,worker)
t.start()
print(threading.enumerate())
t.cancel()
time.sleep(1)
print(threading.enumerate())

python多線程開發(fā)

可以看到,延遲5s執(zhí)行worker線程,然后主線程繼續(xù)執(zhí)行,打印存活的線程,就是主線程和worker線程,然后執(zhí)行cancel,子線程就會(huì)被取消執(zhí)行,sleep 1s后打印存活的線程就只有主線程。

新聞標(biāo)題:python多線程開發(fā)
網(wǎng)頁(yè)路徑:http://www.muchs.cn/article22/jsoecc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供電子商務(wù)、靜態(tài)網(wǎng)站、網(wǎng)站設(shè)計(jì)公司、關(guān)鍵詞優(yōu)化、響應(yīng)式網(wǎng)站網(wǎng)站內(nèi)鏈

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

手機(jī)網(wǎng)站建設(shè)