Python開發基礎-Day29多線程
概念
進程:進程就是一個程序在一個數據集上的一次動態執行過程
程序:代碼
數據集:程序執行過程中需要的資源
進程控制塊:完成狀態保存的單元
線程:線程是寄托在進程之上,為了提高系統的並發性
線程是進程的實體
進程是一個資源管理單元、線程是最小的執行單元
線程和進程的關系
(1)一個線程只能屬於一個進程,而一個進程可以有多個線程,但至少有一個線程。
(2)資源分配給進程,同一進程的所有線程共享該進程的所有資源。
(3)CPU分給線程,即真正在CPU上運行的是線程。
進程/線程切換原則:切換的操作者,操作系統
1、時間片,任務的處理時間
2、遇到io操作,切換
例如socket, accept發了一次系統調用,然後就等待操作系統調用,操作系統進行監聽
3、優先級切換
並發:在一個時間段裏,能夠執行多個程序的能力
切換:即任務狀態的保存,狀態的恢復,是並發的條件
註:為了共用數據集,線程進行切換,線程切換的開銷遠遠小於進程切換的開銷
並行:多個cpu,在同一時刻能夠執行多個程序
同步:同步就是指一個進程在執行某個請求的時候,若該請求需要一段時間才能返回信息,那麽這個進程將會一直等待下去,直到收到返回信息才繼續執行下去
異步:異步是指進程不需要一直等下去,而是繼續執行下面的操作,不管其他進程的狀態。當有消息返回時系統會通知進程進行處理,這樣可以提高執行的效率。
舉個例子,打電話時就是同步通信,發短息時就是異步通信。
python的線程
python加鎖:同一時間只有一個線程出來被執行,在一個進程下實現真正意義上的線程並行,把多核的優勢給浪費了(後邊會講)
threading模塊
Thread類直接創建
1 import threading 2 import time 3 4 def countNum(n): # 定義某個線程要運行的函數 5 6 print("running on number:%s" %n) 7 8 time.sleep(3) 9 10 if __name__ == ‘__main__‘: 11 12 t1 = threading.Thread(target=countNum,args=(23,)) #生成一個線程實例 13 t2 = threading.Thread(target=countNum,args=(34,)) 14 15 t1.start() #啟動線程 16 t2.start() 17 18 print("ending!")
Thread類繼承式創建
#繼承Thread式創建 import threading import time class MyThread(threading.Thread): def __init__(self,num): threading.Thread.__init__(self) self.num=num def run(self): print("running on number:%s" %self.num) time.sleep(3) t1=MyThread(56) t2=MyThread(78) t1.start() t2.start() print("ending")
join()和setDaemon()
# join():在子線程完成運行之前,這個子線程的父線程將一直被阻塞。 # setDaemon(True): ‘‘‘ 將線程聲明為守護線程,必須在start() 方法調用之前設置,如果不設置為守護線程程序會被無限掛起。 當我們在程序運行中,執行一個主線程,如果主線程又創建一個子線程,主線程和子線程 就分兵兩路,分別運行,那麽當主線程完成 想退出時,會檢驗子線程是否完成。如果子線程未完成,則主線程會等待子線程完成後再退出。但是有時候我們需要的是只要主線程 完成了,不管子線程是否完成,都要和主線程一起退出,這時就可以 用setDaemon方法啦‘‘‘ import threading from time import ctime,sleep import time def Music(name): print ("Begin listening to {name}. {time}".format(name=name,time=ctime())) sleep(3) print("end listening {time}".format(time=ctime())) def Blog(title): print ("Begin recording the {title}. {time}".format(title=title,time=ctime())) sleep(5) print(‘end recording {time}‘.format(time=ctime())) threads = [] t1 = threading.Thread(target=Music,args=(‘FILL ME‘,)) t2 = threading.Thread(target=Blog,args=(‘‘,)) threads.append(t1) threads.append(t2) if __name__ == ‘__main__‘: #t2.setDaemon(True) for t in threads: #t.setDaemon(True) #註意:一定在start之前設置 t.start() #t.join() #t1.join() #t2.join() # 考慮這三種join位置下的結果? print ("all over %s" %ctime())
daemon A boolean value indicating whether this thread is a daemon thread (True) or not (False). This must be set before start() is called, otherwise RuntimeError is raised. Its initial value is inherited from the creating thread; the main thread is not a daemon thread and therefore all threads created in the main thread default to daemon = False. The entire Python program exits when no alive non-daemon threads are left. 當daemon被設置為True時,如果主線程退出,那麽子線程也將跟著退出, 反之,子線程將繼續運行,直到正常退出。
其它方法
Thread實例對象的方法 # isAlive(): 返回線程是否活動的。 # getName(): 返回線程名。 # setName(): 設置線程名。 threading模塊提供的一些方法: # threading.currentThread(): 返回當前的線程變量。 # threading.enumerate(): 返回一個包含正在運行的線程的list。正在運行指線程啟動後、結束前,不包括啟動前和終止後的線程。 # threading.activeCount(): 返回正在運行的線程數量,與len(threading.enumerate())有相同的結果。
IO密集型任務:程序中存在大量IO操作
計算密集型任務:程序中存在大量計算操作
對於python而言,處理io密集型任務有優勢,對於計算密集型任務沒優勢
Python開發基礎-Day29多線程