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的線程沒(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é)果如圖所示:
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é)果如圖所示:
可以看到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é)果如圖所示:
主進(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é)果如圖所示:
根據(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é)果如圖所示:
可以看到雖然是全局變量,但是這個(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é)果
在子線程里面打印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())
可以看到,延遲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)