標籤:bsp 結束 cpu 單位 允許 又能 name self 出現
進程與線程
什麼是進程
程式並不能單獨運行,只有將程式裝載到記憶體中,系統為它分配資源才能運行,而這種執行的程式就稱之為進程。程式和進程的區別就在於:程式是指令的集合,它是進程啟動並執行靜態描述文本;進程是程式的一次執行活動,屬於動態概念。
在多道編程中,我們允許多個程式同時載入到記憶體中,在作業系統的調度下,可以實現並發地執行。這是這樣的設計,大大提高了CPU的利用率。進程的出現讓每個使用者感覺到自己獨享CPU,因此,進程就是為了在CPU上實現多道編程而提出的。
有了進程為什麼還要線程?
進程有很多優點,它提供了多道編程,讓我們感覺我們每個人都擁有自己的CPU和其他資源,可以提高電腦的利用率。很多人就不理解了,既然進程這麼優秀,為什麼還要線程呢?其實,仔細觀察就會發現進程還是有很多缺陷的,主要體現在兩點上:
例如,我們在使用qq聊天, qq做為一個獨立進程如果同一時間只能幹一件事,那他如何?在同一時刻 即能監聽鍵盤輸入、又能監聽其它人給你發的訊息、同時還能把別人發的訊息顯示在螢幕上呢?你會說,作業系統不是有分時嗎?但我的親,分時是指在不同進程間的分時呀, 即作業系統處理一會你的qq任務,又切換到word文檔任務上了,每個cpu時間片分給你的qq程式時,你的qq還是只能同時幹一件事呀。
再直白一點, 一個作業系統就像是一個工廠,工廠裡面有很多個生產車間,不同的車間生產不同的產品,每個車間就相當於一個進程,且你的工廠又窮,供電不足,同一時間只能給一個車間供電,為了能讓所有車間都能同時生產,你的工廠的電工只能給不同的車間分時供電,但是輪到你的qq車間時,發現只有一個幹活的工人,結果生產效率極低,為瞭解決這個問題,應該怎麼辦呢?。。。。沒錯,你肯定想到了,就是多加幾個工人,讓幾個人工人並行工作,這每個工人,就是線程!
什麼是線程
線程是作業系統能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運作單位。一條線程指的是進程中一個單一順序的控制流程,一個進程中可以並發多個線程,每條線程並存執行不同的任務
進程和線程的區別
(1)進程是資源的分配和調度的一個獨立單元,而線程是CPU調度的基本單元 (2)同一個進程中可以包括多個線程,並且線程共用整個進程的資源(寄存器、堆棧、上下文),一個進程至少包括一個線程。 (3)進程的建立調用fork或者vfork,而線程的建立調用pthread_create,進程結束後它擁有的所有線程都將銷毀,而線程的結束不會影響同個進程中的其他線程的結束 (4)線程是輕量級的進程,它的建立和銷毀所需要的時間比進程小很多,所有作業系統中的執行功能都是建立線程去完成的 (5)線程中執行時一般都要進行同步和互斥,因為他們共用同一進程的所有資源 (6)線程有自己的私人屬性TCB,線程id,寄存器、硬體上下文,而進程也有自己的私人屬性進程式控制制塊PCB,這些私人屬性是不被共用的,用來標示一個進程或一個線程的標誌 Python threading模組 線程有2種調用方式,如下:直接調用
import threadingimport timedef sayhi(num): # 定義每個線程要啟動並執行函數 print("running on number:%s" % num) time.sleep(3)if __name__ == ‘__main__‘: t1 = threading.Thread(target=sayhi, args=(1,)) # 產生一個線程執行個體 t2 = threading.Thread(target=sayhi, args=(2,)) # 產生另一個線程執行個體 t1.start() # 啟動線程 t2.start() # 啟動另一個線程 print(t1.getName()) # 擷取線程名 print(t2.getName())
繼承式調用
import threadingimport timeclass 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)if __name__ == ‘__main__‘: t1 = MyThread(1) t2 = MyThread(2) t1.start() t2.start() print(t1.getName()) # 擷取線程名 print(t2.getName())
下面是一個對多線程的一個處理方法:(需要理解):
import threadingimport timedef run(n): print("task: ",n) time.sleep(2) print("task done: ",n)start_time = time.time()for i in range(10): t = threading.Thread(target=run,args=(i,)) t.start()print("cost: ",time.time() - start_time)
運行結果如下所示:
是因為這個程式本身就是一個主線程,主線程又起了子線程,這時子線程和主線程已經沒關係了,相當於子線程和主線程是並行的。這就解釋了為什麼我的主線程啟動了子線程之後,沒有等子線程執行完畢,主線程就繼續往下走了。
但是現在有個問題,我們需要計算所有線程的執行時間,並且讓所有線程運行之後再運行主程式
這裡就需要用到線程裡的一個方法join()意思其實就是等待的意思代碼如下:
import threadingimport timedef run(n): print("task: ",n) time.sleep(2) print("task done: ",n)start_time = time.time()t_obj = [] #存線程執行個體for i in range(10): t = threading.Thread(target=run,args=(i,)) t.start() t_obj.append(t) #為了不阻塞後麵線程的啟動,不在這裡join,先放到一個列表裡for i in t_obj: #迴圈線程執行個體列表,等待所有線程執行完畢 i.join()print("all thread is done")print("cost: ",time.time() - start_time)
沒有加join的時候,主線程不會等子線程執行完畢再往下走,主線程和子線程的執行完全是並行的,沒有依賴關係,你執行,我也執行。但是,你會發現,最終退出的時候,主線程依然會等待所有的子線程執行完畢才退出程式。雖然不等你執行完畢才往下走,但是在程式退出之前,會預設還有一個join
但加了join的時候,主線程依賴子線程執行完畢之後, 再往下走,這是JOIN 的作用。
關於守護線程
如果將線程設定為守護線程,則主程式不會管線程是否執行完,只有主程式執行完畢之後,就會結束
代碼例子如下:
import threadingimport timedef run(n): print("task: ",n) time.sleep(2) print("task done: ",n)start_time = time.time()for i in range(10): t = threading.Thread(target=run,args=(i,)) t.setDaemon(True) #把當前線程設定為守護線程 t.start()print("all thread is done",threading.current_thread(),threading.active_count())print("cost: ",time.time() - start_time)
Python 基礎之-進程、線程