串行程序必須使用非阻塞I/O,或擁有計時器的阻塞I/O,需兼顧要執(zhí)行的多個任務(wù),難以維護。
多線程編程,以及多線程隊列數(shù)據(jù)結(jié)構(gòu),包含如下幾個執(zhí)行特定函數(shù)的線程:
UserRequestThread:讀取客戶端輸入,放入隊列
RequestProcessor:從隊列中獲取請求并處理
ReplyThread:結(jié)果回傳用戶 or 把數(shù)據(jù)寫入本地數(shù)據(jù)庫
1 線程和進程
1.1 進程:一個運行中的程序
1.2 線程:在同一進程下執(zhí)行,共享上下文,共享同一片數(shù)據(jù)空間。當(dāng)線程運行時,可以被中斷和臨時掛起
2 線程和python
2.1 全局解釋器鎖(GIL)
python解釋器可以運行多個線程,但任意時刻,只有一個線程會被解釋器執(zhí)行。
(1-設(shè)置GIL,2-切換1個線程執(zhí)行,3-(執(zhí)行數(shù)量的字節(jié)碼指令 Or 線程讓出控制權(quán) time.sleep(0),4-設(shè)置線程為睡眠狀態(tài),5-解鎖GIL))
2.2 退出線程
當(dāng)一個線程完成函數(shù)執(zhí)行,會退出。也可以通過調(diào)用thread.exit()退出函數(shù)、sys.exit()退出Python進程、拋出SystemExit異常來使線程退出。
2.3 在python中使用線程
避免使用thread模塊,因為對于進程何時退出沒有控制。當(dāng)主線程結(jié)束時,所有其他線程也都強制結(jié)束。
2.4 thread模塊
thread模塊提供了基本的同步數(shù)據(jù)結(jié)構(gòu)---鎖對象,核心函數(shù) start_new_thread(func,args),派生新的線程來調(diào)用這個函數(shù)。此外還有 allocate_lock()---分配鎖對象? ?exit()---退出線程
"start_new_thread() 必須包含開始的2個參數(shù),即使函數(shù)func不需參數(shù),也要傳遞空元祖進去"
"引入鎖,目的為了在所有線程結(jié)束后立刻退出"
鎖對象方法:
1 acquire() 獲取
2 locked() 如果獲取了 返回True
3 release() 釋放
2.5 threading模塊
threading模塊包含的對象
threading模塊支持守護線程,一般是一個等待客戶端請求服務(wù)的服務(wù)器,如果主線程準(zhǔn)備退出,不需要等待某個子線程完成,可以給這個子線程設(shè)置守護線程標(biāo)記,需要在啟動線程之前賦值語句,thread.daemon = True,一個新的子線程會繼承父線程的守護標(biāo)記。
2.5.1 Thread類
Thread對象屬性
name---線程名
ident 線程標(biāo)識符
daemon--是否是守護線程
Thread對象方法
__init__(group=None, target=None, args())
start()
run()---定義線程功能的方法
join(timeout=None)---直至啟動的線程終止之前一直掛起,除非有timeout,否則一直阻塞。
使用Thread類,創(chuàng)建線程的方法:
1 創(chuàng)建Thread實例,傳給它一個函數(shù)。
? ?實例化Thread和調(diào)用thread.start_new_thread()最大的區(qū)別是,新線程不會立即開始執(zhí)行。通過調(diào)用每個線程的start()方法開始執(zhí)行,join()方法等待線程結(jié)束。
2 派生Thread的子類,并創(chuàng)建子類的實例。
class MyThread(threading.Thread):
? ? ? def __init__(self, func, args, name=' '):? ?
? ? ? ? ? ? threading.Thread.__init__(self)? ? #調(diào)用父類構(gòu)造函數(shù)初始化父類
為了讓子類更加通用,專門配置一個模塊,便于以后導(dǎo)入。把結(jié)果保存在實例屬性中,并新建一個方法來獲取值。

2.6 單線程和多線程執(zhí)行對比