Python 并發編程之 Threading 模塊
threading模塊
multiprocess模塊的完全模仿了threading模塊的接口,二者在使用層面,有很大的相似性,因而不再詳細介紹(官方鏈接)
線程的創建Threading.Thread類
創建線程的方式一:
from?threading?import?Thread import?time def?sayhi(name): ????time.sleep(2) ????print('%s?say?hello'?%name) if?__name__?==?'__main__': ????t=Thread(target=sayhi,args=('egon',)) ????t.start() ????print('主線程')
創建線程的方式2:
from?threading?import?Thread import?time class?Sayhi(Thread): ????def?__init__(self,name): ????????super().__init__() ????????self.name=name ????def?run(self): ????????time.sleep(2) ????????print('%s?say?hello'?%?self.name) if?__name__?==?'__main__': ????t?=?Sayhi('egon') ????t.start() ????print('主線程')
pid的比較:
from?threading?import?Thread from?multiprocessing?import?Process import?os def?work(): ????print('hello',os.getpid()) if?__name__?==?'__main__': ????#part1:在主進程下開啟多個線程,每個線程都跟主進程的pid一樣 ????t1=Thread(target=work) ????t2=Thread(target=work) ????t1.start() ????t2.start() ????print('主線程/主進程pid',os.getpid()) ????#part2:開多個進程,每個進程都有不同的pid ????p1=Process(target=work) ????p2=Process(target=work) ????p1.start() ????p2.start() ????print('主線程/主進程pid',os.getpid())
開啟效率的較量:
from?threading?import?Thread from?multiprocessing?import?Process import?os def?work(): ????print('hello') if?__name__?==?'__main__': ????#在主進程下開啟線程 ????t=Thread(target=work) ????t.start() ????print('主線程/主進程') ????''' ????打印結果: ????hello ????主線程/主進程 ????''' ????#在主進程下開啟子進程 ????t=Process(target=work) ????t.start() ????print('主線程/主進程') ????''' ????打印結果: ????主線程/主進程 ????hello ????'''
內存數據的共享問題:
from??threading?import?Thread from?multiprocessing?import?Process import?os def?work(): ????global?n ????n=0 if?__name__?==?'__main__': ????#?n=100 ????#?p=Process(target=work) ????#?p.start() ????#?p.join() ????#?print('主',n)?#毫無疑問子進程p已經將自己的全局的n改成了0,但改的僅僅是它自己的,查看父進程的n仍然為100 ????n=1 ????t=Thread(target=work) ????t.start() ????t.join() ????print('主',n)?#查看結果為0,因為同一進程內的線程之間共享進程內的數據 同一進程內的線程共享該進程的數據?
server:
#_*_coding:utf-8_*_ #!/usr/bin/env?python import?multiprocessing import?threading import?socket s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.bind(('127.0.0.1',8080)) s.listen(5) def?action(conn): ????while?True: ????????data=conn.recv(1024) ????????print(data) ????????conn.send(data.upper()) if?__name__?==?'__main__': ????while?True: ????????conn,addr=s.accept() ????????p=threading.Thread(target=action,args=(conn,)) ????????p.start()
clent:
#_*_coding:utf-8_*_ #!/usr/bin/env?python import?socket s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect(('127.0.0.1',8080)) while?True: ????msg=input('>>:?').strip() ????if?not?msg:continue ????s.send(msg.encode('utf-8')) ????data=s.recv(1024) ????print(data)
Thread實例對象的方法 ??#?isAlive():?返回線程是否活動的。 ??#?getName():?返回線程名。 ??#?setName():?設置線程名。 threading模塊提供的一些方法: ??#?threading.currentThread():?返回當前的線程變量。 ??#?threading.enumerate():?返回一個包含正在運行的線程的list。正在運行指線程啟動后、結束前,不包括啟動前和終止后的線程。 ??#?threading.activeCount():?返回正在運行的線程數量,與len(threading.enumerate())有相同的結果。
代碼示例:
from?threading?import?Thread import?threading from?multiprocessing?import?Process import?os def?work(): ????import?time ????time.sleep(3) ????print(threading.current_thread().getName()) if?__name__?==?'__main__': ????#在主進程下開啟線程 ????t=Thread(target=work) ????t.start() ????print(threading.current_thread().getName()) ????print(threading.current_thread())?#主線程 ????print(threading.enumerate())?#連同主線程在內有兩個運行的線程 ????print(threading.active_count()) ????print('主線程/主進程') ????''' ????打印結果: ????MainThread ????<_MainThread(MainThread,?started?140735268892672)> ????[<_MainThread(MainThread,?started?140735268892672)>,?
join方法:
from?threading?import?Thread import?time def?sayhi(name): ????time.sleep(2) ????print('%s?say?hello'?%name) if?__name__?==?'__main__': ????t=Thread(target=sayhi,args=('egon',)) ????t.start() ????t.join() ????print('主線程') ????print(t.is_alive()) ????''' ????egon?say?hello ????主線程 ????False ????'''
無論是進程還是線程,都遵循:守護xx會等待主xx運行完畢后被銷毀。需要強調的是:運行完畢并非終止運行
#1.對主進程來說,運行完畢指的是主進程代碼運行完畢 #2.對主線程來說,運行完畢指的是主線程所在的進程內所有非守護線程統統運行完畢,主線程才算運行完畢
詳細解釋:
#1?主進程在其代碼結束后就已經算運行完畢了(守護進程在此時就被回收), 然后主進程會一直等非守護的子進程都運行完畢后回收子進程的資源(否則會產生僵尸進程),才會結束, #2?主線程在其他非守護線程運行完畢后才算運行完畢(守護線程在此時就被回收)。因為主線程的結束意味著進程的結束,進程整體的資源都將被回收, 而進程必須保證非守護線程都運行完畢后才能結束。
守護線程示例1:
from?threading?import?Thread import?time def?sayhi(name): ????time.sleep(2) ????print('%s?say?hello'?%name) if?__name__?==?'__main__': ????t=Thread(target=sayhi,args=('egon',)) ????t.setDaemon(True)?#必須在t.start()之前設置 ????t.start() ????print('主線程') ????print(t.is_alive()) ????''' ????主線程 ????True ????'''
守護線程示例2:
from?threading?import?Thread import?time def?foo(): ????print(123) ????time.sleep(1) ????print("end123") def?bar(): ????print(456) ????time.sleep(3) ????print("end456") t1=Thread(target=foo) t2=Thread(target=bar) t1.daemon=True t1.start() t2.start() print("main-------")
軟件開發 人工智能 云計算 機器學習
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。