【執行緒理論】
1 1.什麼是執行緒? 2 程序:資源單位,僅僅是在記憶體空間中開闢一塊獨立的空間 3 執行緒:程式執行單位(真正被CPU執行的其實是程序裡面的執行緒,執行緒指的就是程式碼的執行過程,執行程式碼中所需要使用到的資源都找所在的程序索要) 4 (每一個程序自帶一個執行緒) 5 6 2.為什麼要有執行緒 7 開設程序: 8 1.申請記憶體空間 耗資源 9 2.“複製程式碼” 耗資源 10 開執行緒: 11 一個程序內可以開設多個執行緒,在用一個程序內開設多個執行緒無需再次申請記憶體空間及靠欸程式碼的操作 12 總結:開設執行緒比開設程序的開銷小,同一個程序下的多個執行緒資料是共享的
3.程序之間和執行緒之間是合作還是競爭?
程序是開闢出的獨立的記憶體地址 ---> 搶資源 (記憶體、硬碟、網路 ... ) ---> 對於程序與程序之間來說 競爭
執行緒是開設在程序內部 --> 共享一塊資源 ----> 對於執行緒來說是合作
4.什麼是多執行緒
多執行緒指的是
在一個程序中開啟多個執行緒
簡單的講:如果多個任務共用一塊地址空間,那麼必須在一個程序內開啟多個執行緒。
多執行緒共享一個程序的地址空間
執行緒比程序更輕量級,執行緒比程序更容易建立可撤銷,在許多作業系統中,建立一個執行緒比建立一個程序要快10-100倍,在有大量執行緒需要動態和快速修改時,這一特性很有用
若多個執行緒都是cpu密集型的,那麼並不能獲得效能上的增強
但是如果存在大量的計算和大量的I/O處理,擁有多個執行緒允許這些活動彼此重疊執行,從而會加快程式執行的速度。
在多cpu系統中,為了最大限度的利用多核,可以開啟多個執行緒,比開程序開銷要小的多。(這一條並不適用於Python)
【建立執行緒的兩種方式】
1 第一種: 2 3 def task(name): 4 print('%s is running' % name) 5 time.sleep(2) 6 print('%s is over' % name) 7 8 9 # 開啟執行緒不需要在main下面執行程式碼,直接書寫就可以 10 t = Thread(target=task, args=('egon',)) 11 t.start() # 建立執行緒的開銷非常小,幾乎是程式碼一執行執行緒就已經建立好啦 12 print('主') 13 14 15 ================================================ 16 第二種: 17 18 from threading import Thread 19 import time 20 21 22 # (類繼承) 23 class MyThead(Thread): 24 def __init__(self, name): 25 # 重寫別人的方法,又不知道別人的方法裡有啥,就呼叫父類的方法 26 super().__init__() 27 self.name = name 28 29 def run(self): 30 print('%s is running' % self.name) 31 time.sleep(1) 32 print('小可愛') 33 34 35 if __name__ == '__main__': 36 t = MyThead('egon') 37 t.start() 38 print('主') 39 這行程式碼可能線上程開始之前、之中或之後列印,取決於作業系統的執行緒排程 40 ================= 41 先執行running,再執行主
。
。
【TCP服務端實現併發】
1 服務端 2 3 import socket 4 from threading import Thread 5 from multiprocessing import Process 6 7 ''' 8 服務端: 9 1.要有固定的IP和PORT 10 2.24小時不斷提供服務 11 3.能夠支援併發 12 ''' 13 server = socket.socket() # 括號內不加引數預設就是TCP協議 14 server.bind(('127.0.0.1', 8080)) 15 server.listen(5) 16 17 18 # 將服務的程式碼單獨封裝成一個函式 19 def talk(conn): 20 # 通訊迴圈 21 while True: 22 try: 23 data = conn.recv(1024) 24 if len(data) == 0: break 25 print(data.decode('utf-8')) 26 conn.send(data.upper()) 27 except ConnectionResetError as e: 28 print(e) 29 break 30 conn.close() 31 32 33 # 連結迴圈 34 while True: 35 conn, addr = server.accept() 36 # # 叫其他人來服務客戶 37 t = Thread(target=talk, args=(conn,)) 38 t.start() # 啟動執行緒,實現併發 39 40 41 ================================================ 42 客戶端 43 44 import socket 45 46 client = socket.socket() 47 client.connect(('127.0.0.1',8080)) 48 while True: 49 client.send(b'hello world') 50 data = client.recv(1024) 51 print(data.decode('utf-8'))
。
。
【join 方法】
1 from threading import Thread 2 import time 3 4 5 def task(name): 6 print('%s is running' % name) 7 time.sleep(1) 8 print('%s is over' % name) 9 10 11 if __name__ == '__main__': 12 t = Thread(target=task, args=('egon',)) 13 t.start() 14 # 想等到子執行緒執行完畢在執行 15 t.join() 16 print('主')
。
。
【執行緒的諸多特性】
1.執行緒的join方法,主執行緒程式碼等待子執行緒程式碼執行結束再往下執行!!! (和執行緒的join方法特性一樣)
2.同一個程序內多個執行緒資料共享
3.current_thread().name # 檢視程序下的執行緒名
4.active_count() # 檢視程序下的執行緒數
1 from threading import Thread 2 import time 3 4 # ========================驗證同一個程序下的多個執行緒資料共享 5 money = 100 6 7 8 def task(): 9 global money 10 money = 666 11 12 13 if __name__ == '__main__': 14 t = Thread(target=task) 15 t.start() 16 # t.join() 17 print(money) # 666 18 19 20 ------------------------------------------ 21 同一個程序內多個執行緒資料共享,所以子執行緒將主執行緒裡面的全域性變數money的值改了, 22 主執行緒與子執行緒都在一個程序裡面,都在一個記憶體空間內。
。
。
【執行緒物件及其他方法】
1 # 執行緒物件及其他方法 2 import os, time 3 from threading import Thread, active_count, current_thread 4 5 6 def task(): 7 print('hello world', os.getpid()) 8 print('hello', current_thread().name) # 獲取執行緒名字,Thread-1 9 10 11 if __name__ == '__main__': 12 t = Thread(target=task) 13 t.start() 14 print('主', os.getpid()) # 兩個程序號一樣,證明兩個執行緒在同一個程序下 15 print('主執行緒名字', current_thread().name) # MainThread 16 print('主', active_count()) # 統計當前正在活躍的執行緒數 17 18 19 --------------------------------------------------------------------------------- 20 active_count:統計當前正在活躍的執行緒數 21 22 current_thread().name獲取執行緒名字