多线程 VS 多进程(一)
生活随笔
收集整理的這篇文章主要介紹了
多线程 VS 多进程(一)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
多線程 vs 多進(jìn)程
-
程序:一堆代碼以文本形式存入一個(gè)文檔
-
進(jìn)程:程序運(yùn)行的一個(gè)狀態(tài)
- 包含地址空間、內(nèi)容、數(shù)據(jù)棧等
- 每個(gè)進(jìn)程由自己完全獨(dú)立的運(yùn)行環(huán)境,多進(jìn)程共享數(shù)據(jù)是一個(gè)問題
-
線程
- 一個(gè)進(jìn)程的獨(dú)立運(yùn)行片段,一個(gè)進(jìn)程可以有多個(gè)線程
- 輕量化的進(jìn)程
- 一個(gè)進(jìn)程的多個(gè)線程間共享數(shù)據(jù)和上下文運(yùn)行環(huán)境
- 共享互斥問題
-
全局解釋器鎖(GTL)
- python 代碼的執(zhí)行是由python 虛擬機(jī)進(jìn)行控制
- 在主循環(huán)中只能有一個(gè)控制線程在執(zhí)行
-
python 包
-
thread:有問題,不好用,python3改成了_thread
-
threading:通行的包
-
案例01: 順序執(zhí)行,耗時(shí)比較長(zhǎng)
'''利用time函數(shù),生成兩個(gè)函數(shù)程序調(diào)試計(jì)算總的運(yùn)行時(shí)間'''import timedef loop1():# ctime 得到當(dāng)前時(shí)間print("Start loop 1 at : ",time.ctime())time.sleep(4)print("End loop 1 at : ", time.ctime())def loop2():# ctime 得到當(dāng)前時(shí)間print("Start loop 2 at : ", time.ctime())# 睡眠多長(zhǎng)時(shí)間,單位是秒time.sleep(2)print("End loop 2 at : ", time.ctime())def main():print("Starting at : ", time.ctime())loop1()loop2()print("All done at : ", time.ctime())if __name__ == '__main__':main() Starting at : Tue Aug 13 19:10:31 2019Start loop 1 at : Tue Aug 13 19:10:31 2019End loop 1 at : Tue Aug 13 19:10:35 2019Start loop 2 at : Tue Aug 13 19:10:35 2019End loop 2 at : Tue Aug 13 19:10:37 2019All done at : Tue Aug 13 19:10:37 2019 -
案例02:改用多線程,縮短總時(shí)間,使用_thread
''' 利用time函數(shù),生成兩個(gè)函數(shù) 程序調(diào)試 計(jì)算總的運(yùn)行時(shí)間 '''import time import _thread as thread def loop1():# ctime 得到當(dāng)前時(shí)間print("Start loop 1 at : ",time.ctime())time.sleep(4)print("End loop 1 at : ", time.ctime())def loop2():# ctime 得到當(dāng)前時(shí)間print("Start loop 2 at : ", time.ctime())# 睡眠多長(zhǎng)時(shí)間,單位是秒time.sleep(2)print("End loop 2 at : ", time.ctime())def main():print("Starting at : ", time.ctime())# 啟動(dòng)多線程的意思是用多線程去執(zhí)行某個(gè)函數(shù)# 啟動(dòng)多線程函數(shù)為start_new_thread# 參數(shù)兩個(gè),一個(gè)是需要運(yùn)行的函數(shù)名,第二個(gè)是函數(shù)的參數(shù)作為元組使用,為空則使用空元組# 注意,如果函數(shù)只有一個(gè)參數(shù),需要參數(shù)后有一個(gè)逗號(hào)thread.start_new_thread(loop1, ())thread.start_new_thread(loop2, ())print("All done at : ", time.ctime())if __name__ == '__main__':main()while True:time.sleep(1) Starting at : Tue Aug 13 19:14:47 2019All done at : Tue Aug 13 19:14:47 2019Start loop 1 at : Tue Aug 13 19:14:47 2019Start loop 2 at : Tue Aug 13 19:14:47 2019End loop 2 at : Tue Aug 13 19:14:49 2019End loop 1 at : Tue Aug 13 19:14:51 2019 -
案例03:多線程,傳參數(shù)
# 利用time延時(shí)函數(shù),生成兩個(gè)函數(shù) # 利用多線程調(diào)用 # 計(jì)算總運(yùn)行時(shí)間 # 練習(xí)帶參數(shù)的多線程啟動(dòng)方法 import time # 導(dǎo)入多線程包并更名為thread import _thread as threaddef loop1(in1):# ctime 得到當(dāng)前時(shí)間print('Start loop 1 at: ', time.ctime())# 把參數(shù)打印出來(lái)print("我是參數(shù)", in1)# 睡眠多長(zhǎng)時(shí)間,單位是秒time.sleep(4)print('End loop 1 at: ', time.ctime())def loop2(in1, in2):# ctime 得到當(dāng)前時(shí)間print('Start loop 2 at: ', time.ctime())# 把參數(shù)in1 和 in2 打印出來(lái),代表使用print("我是參數(shù)", in1, "和參數(shù)", in2)# 睡眠多長(zhǎng)時(shí)間,單位是秒time.sleep(4)print('End loop 2 at: ', time.ctime())def main():print("Starting at : ", time.ctime())# 啟動(dòng)多線程的意思是用多線程去執(zhí)行某個(gè)函數(shù)# 啟動(dòng)多線程函數(shù)為start_new_thread# 參數(shù)兩個(gè),一個(gè)是需要運(yùn)行的函數(shù)名,第二個(gè)是函數(shù)的參數(shù)作為元組使用,為空則使用空元組# 注意,如果函數(shù)只有一個(gè)參數(shù),需要參數(shù)后有一個(gè)逗號(hào)thread.start_new_thread(loop1, ("王老大", ))thread.start_new_thread(loop2, ("王大鵬", "王曉鵬"))print("All done at : ", time.ctime())if __name__ == '__main__':main()# 一定要有while語(yǔ)句# 因?yàn)閱?dòng)多線程后本程序就作為主線程存在# 如果主線程執(zhí)行完畢,則子線程可能也需要終止while True:time.sleep(10) Starting at : Tue Aug 13 19:17:10 2019All done at : Tue Aug 13 19:17:10 2019Start loop 1 at: Tue Aug 13 19:17:10 2019我是參數(shù) 王老大Start loop 2 at: Tue Aug 13 19:17:10 2019我是參數(shù) 王大鵬 和參數(shù) 王曉鵬End loop 1 at: Tue Aug 13 19:17:14 2019End loop 2 at: Tue Aug 13 19:17:14 2019
-
-
threading的使用
- 直接利用threading.Thread生成Thread實(shí)例
- t = threading.Thread(target=xxx, args=(xxx, ))
- t.start(): 啟動(dòng)多線程
- t.join(): 等待多線程執(zhí)行完成
- 案例04# 利用time延時(shí)函數(shù),生成兩個(gè)函數(shù) # 利用多線程調(diào)用 # 計(jì)算總運(yùn)行時(shí)間 # 練習(xí)帶參數(shù)的多線程啟動(dòng)方法 import time # 導(dǎo)入多線程包并更名為thread import threadingdef loop1(in1):# ctime 得到當(dāng)前時(shí)間print('Start loop 1 at: ', time.ctime())# 把參數(shù)打印出來(lái)print("我是參數(shù)", in1)# 睡眠多長(zhǎng)時(shí)間,單位是秒time.sleep(4)print('End loop 1 at: ', time.ctime())def loop2(in1, in2):# ctime 得到當(dāng)前時(shí)間print('Start loop 2 at: ', time.ctime())# 把參數(shù)in1 和 in2 打印出來(lái),代表使用print("我是參數(shù)", in1, "和參數(shù) ", in2)# 睡眠多長(zhǎng)時(shí)間,單位是秒time.sleep(2)print('End loop 2 at: ', time.ctime())def main():print("Starting at: ", time.ctime())# 生成threading.Thread實(shí)例t1 = threading.Thread(target=loop1, args=("王老大",))t1.start()t2 = threading.Thread(target=loop2, args=("王大鵬", "王小鵬"))t2.start()print("All done at: ", time.ctime())if __name__ == '__main__':main()# 一定要有while語(yǔ)句# 因?yàn)閱?dòng)多線程后本程序就作為主線程存在# 如果主線程執(zhí)行完畢,則子線程可能也需要終止while True:time.sleep(10) Starting at: Tue Aug 13 19:19:42 2019Start loop 1 at: Tue Aug 13 19:19:42 2019我是參數(shù) 王老大Start loop 2 at: All done at: Tue Aug 13 19:19:42 2019Tue Aug 13 19:19:42 2019我是參數(shù) 王大鵬 和參數(shù) 王小鵬End loop 2 at: Tue Aug 13 19:19:44 2019End loop 1 at: Tue Aug 13 19:19:46 2019
- 案例05:加入join后比較案例04的結(jié)果的異同# 利用time延時(shí)函數(shù),生成兩個(gè)函數(shù) # 利用多線程調(diào)用 # 計(jì)算總運(yùn)行時(shí)間 # 練習(xí)帶參數(shù)的多線程啟動(dòng)方法 import time # 導(dǎo)入多線程包并更名為thread import threadingdef loop1(in1):# ctime 得到當(dāng)前時(shí)間print('Start loop 1 at: ', time.ctime())# 把參數(shù)打印出來(lái)print("我是參數(shù)", in1)# 睡眠多長(zhǎng)時(shí)間,單位是秒time.sleep(4)print('End loop 1 at: ', time.ctime())def loop2(in1, in2):# ctime 得到當(dāng)前時(shí)間print('Start loop 2 at: ', time.ctime())# 把參數(shù)in1 和 in2 打印出來(lái),代表使用print("我是參數(shù)", in1, "和參數(shù) ", in2)# 睡眠多長(zhǎng)時(shí)間,單位是秒time.sleep(2)print('End loop 2 at: ', time.ctime())def main():print("Starting at: ", time.ctime())# 生成threading.Thread實(shí)例t1 = threading.Thread(target=loop1, args=("王老大",))t1.start()t2 = threading.Thread(target=loop2, args=("王大鵬", "王小鵬"))t2.start()t1.join()t2.join()print("All done at: ", time.ctime())if __name__ == '__main__':main()# 一定要有while語(yǔ)句# 因?yàn)閱?dòng)多線程后本程序就作為主線程存在# 如果主線程執(zhí)行完畢,則子線程可能也需要終止while True:time.sleep(10) Starting at: Tue Aug 13 19:21:58 2019Start loop 1 at: Tue Aug 13 19:21:58 2019我是參數(shù) 王老大Start loop 2 at: Tue Aug 13 19:21:58 2019我是參數(shù) 王大鵬 和參數(shù) 王小鵬End loop 2 at: Tue Aug 13 19:22:00 2019End loop 1 at: Tue Aug 13 19:22:02 2019All done at: Tue Aug 13 19:22:02 2019
- 守護(hù)線程-daemon
- 如果在程序中將子線程設(shè)置成守護(hù)線程,則子線程會(huì)在主線程結(jié)束的時(shí)候自動(dòng)退出
- 一般認(rèn)為,守護(hù)線程不重要或者不允許離開主線程獨(dú)立運(yùn)行
- 守護(hù)線程案例能否有效果跟環(huán)境相關(guān)
- 案例06非守護(hù)線程import time import threadingdef fun():print("Start fun")time.sleep(2)print("end fun")print("Main thread")t1 = threading.Thread(target=fun, args=() ) t1.start()time.sleep(1) print("Main thread end") Main threadStart funMain thread endend fun
- 案例07守護(hù)線程import time import threadingdef fun():print("Start fun")time.sleep(2)print("end fun")print("Main thread")t1 = threading.Thread(target=fun, args=() ) # 啟動(dòng)之前設(shè)置 t1.setDaemon(True) # t1.daemon = True t1.start()time.sleep(1) print("Main thread end") Main threadStart funMain thread end
- 線程常用屬性
- threading.currentThread:返回當(dāng)前線程變量
- threading.enumerate:返回一個(gè)包含正在運(yùn)行的線程的list,正在運(yùn)行的線程指的是線程啟動(dòng)后,結(jié)束前的狀態(tài)
- threading.activeCount: 返回正在運(yùn)行的線程數(shù)量,效果跟 len(threading.enumerate)相同
- thr.setName: 給線程設(shè)置名字
- thr.getName: 得到線程的名字
- 案例08import time import threadingdef loop1():# ctime 得到當(dāng)前時(shí)間print("Start loop 1 at : ",time.ctime())time.sleep(6)print("End loop 1 at : ", time.ctime())def loop2():# ctime 得到當(dāng)前時(shí)間print("Start loop 2 at : ",time.ctime())time.sleep(1)print("End loop 2 at : ", time.ctime())def loop3():# ctime 得到當(dāng)前時(shí)間print("Start loop 3 at : ",time.ctime())time.sleep(5)print("End loop 3 at : ", time.ctime())def main():print("Starting at: ", time.ctime())# 生成threading.Thread實(shí)例t1 = threading.Thread(target=loop1, args=( ))# setName是給每一個(gè)子線程設(shè)置一個(gè)名字t1.setName("THR_1")t1.start()t2 = threading.Thread(target=loop2, args=( ))t2.setName("THR_2")t2.start()t3 = threading.Thread(target=loop3, args=( ))t3.setName("THR_3")t3.start()# 預(yù)期3秒后,thread2已經(jīng)結(jié)束time.sleep(3)# enumerate 得到正在運(yùn)行子線程,即子線程1和子線程3for thr in threading.enumerate():# getName能夠得到線程的名字print("正在運(yùn)行的線程名字是: {0}".format(thr.getName()))print("正在運(yùn)行的子線程數(shù)量為: {0}".format(threading.activeCount()))print("All done at: ", time.ctime())if __name__ == '__main__':main()# 一定要有while語(yǔ)句# 因?yàn)閱?dòng)多線程后本程序就作為主線程存在# 如果主線程執(zhí)行完畢,則子線程可能也需要終止while True:time.sleep(10) Starting at: Tue Aug 13 19:28:20 2019Start loop 1 at : Tue Aug 13 19:28:20 2019Start loop 2 at : Tue Aug 13 19:28:20 2019Start loop 3 at : Tue Aug 13 19:28:20 2019End loop 2 at : Tue Aug 13 19:28:21 2019正在運(yùn)行的線程名字是: MainThread正在運(yùn)行的線程名字是: THR_1正在運(yùn)行的線程名字是: THR_3正在運(yùn)行的子線程數(shù)量為: 3All done at: Tue Aug 13 19:28:23 2019End loop 3 at : Tue Aug 13 19:28:25 2019End loop 1 at : Tue Aug 13 19:28:26 2019
- 直接繼承自threading.Thread
- 直接繼承Thread
- 重寫run函數(shù)
- 類實(shí)例可以直接運(yùn)行
- 案例09import threading import time# 1. 類需要繼承來(lái)自threading.Thread class MyThread(threading.Thread):def __init__(self, arg):super().__init__()self.arg = arg# 2. 必須重寫run函數(shù),run函數(shù)代表的是真正執(zhí)行的功能def run(self):time.sleep(2)print("The args for this class is {0}".format(self.arg))for i in range(5):t = MyThread(i)t.start()t.join()print("Main thread is done!!!!!!!!") The args for this class is 0The args for this class is 1The args for this class is 2The args for this class is 3The args for this class is 4Main thread is done!!!!!!!!
- 案例10 工業(yè)風(fēng)案例import threading from time import sleep, ctimeloop = [4, 2]class ThreadFunc:def __init__(self, name):self.name = namedef loop(self, nloop, nsec):''':param nloop:loop函數(shù)的名稱:param nsec:系統(tǒng)休眠時(shí)間:return:'''print('Start loop', nloop, 'at ', ctime())sleep(nsec)print('Done loop', nloop, 'at ', ctime())def main():print("Starting at: ", ctime())# ThreadFunc("loop").loop 跟以下兩個(gè)式子相等# t = ThreadFunc("loop")# t.loop# 以下t1 和 t2的定義方式相等t = ThreadFunc("loop")t1 = threading.Thread( target=t.loop, args=("LOOP1", 4))# 下面這種寫法更西方人,工業(yè)化一點(diǎn)t2 = threading.Thread( target=ThreadFunc('loop').loop, args=('LOOP2', 2))# 常見錯(cuò)誤寫法# t1 = threading.Thread(target=ThreadFunc('loop').loop(100,4))# t2 = threading.Thread(target=ThreadFunc('loop').loop(100,2))t1.start()t2.start()t1.join()t2.join()print("All done at: ", ctime())if __name__ == '__main__':main()# 一定要有while語(yǔ)句# 因?yàn)閱?dòng)多線程后本程序就作為主線程存在# 如果主線程執(zhí)行完畢,則子線程可能也需要終止while True:sleep(10) Starting at: Tue Aug 13 19:31:16 2019Start loop LOOP1 at Tue Aug 13 19:31:16 2019Start loop LOOP2 at Tue Aug 13 19:31:16 2019Done loop LOOP2 at Tue Aug 13 19:31:18 2019Done loop LOOP1 at Tue Aug 13 19:31:20 2019All done at: Tue Aug 13 19:31:20 2019
總結(jié)
以上是生活随笔為你收集整理的多线程 VS 多进程(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CompletableFuture原理与
- 下一篇: 关于线性稳压器的五个设计细节