一、應用程序網絡
import threading print('666') def func(arg): print(arg) t = threading.Thread(target=func) t.start() print('end')
二、線程的使用多線程
import threading 1.線程的基本使用 def func(arg): print(arg) t = threading.Thread(target=func,args=(11,)) t.start() print(123) 2.主線程默認等子線程執行完畢 import time def func(arg): time.sleep(arg) print(arg) t1 = threading.Thread(target=func,args=(3,)) t1.start() t2 = threading.Thread(target=func,args=(9,)) t2.start() print(123) 3.主線程再也不等,主線程終止則全部子線程終止 import time def func(arg): time.sleep(2) print(arg) t1 = threading.Thread(target=func,args=(3,)) t1.setDaemon(True) t1.start() t2 = threading.Thread(target=func,args=(9,)) t2.setDaemon(True) t2.start() print(123) 4.開發者能夠控制主線程等待子線程(最多等待時間) import time def func(arg): time.sleep(0.01) print(arg) print('建立子線程t1') t1 = threading.Thread(target=func,args=(3,)) t1.start() # 無參數,讓主線程在這裏等着,等到子線程t1執行完畢,才能夠繼續往下走。 # 有參數,讓主線程在這裏最多等待n秒,不管是否執行完畢,會繼續往下走。 t1.join(2) print('建立子線程t2') t2 = threading.Thread(target=func,args=(9,)) t2.start() t2.join(2) # 讓主線程在這裏等着,等到子線程t2執行完畢,才能夠繼續往下走。 print(123) 4.線程名稱 def func(arg): # 獲取當前執行該函數的線程的對象 t = threading.current_thread() # 根據當前線程對象獲取當前線程名稱 name = t.getName() print(name,arg) t1 = threading.Thread(target=func,args=(11,)) t1.setName('侯明魏') t1.start() t2 = threading.Thread(target=func,args=(22,)) t2.setName('劉寧錢') t2.start() print(123) 5.線程本質 # 先打印:11?123? def func(arg): print(arg) t1 = threading.Thread(target=func,args=(11,)) t1.start() # start 是開始運行線程嗎?不是 # start 告訴cpu,我已經準備就緒,你能夠調度我了。 print(123) 6.補充:面向對象版本的多線程 # 多線程方式:1 (常見) def func(arg): print(arg) t1 = threading.Thread(target=func,args=(11,)) t1.start() # 多線程方式:2 class MyThread(threading.Thread): def run(self): print(11111,self._args,self._kwargs) t1 = MyThread(args=(11,)) t1.start() t2 = MyThread(args=(22,)) t2.start() print('end')
三、多線程socket
import threading 1. 計算密集型多線程無用 v1 = [11,22,33] # +1 v2 = [44,55,66] # 100 def func(data,plus): for i in range(len(data)): data[i] = data[i] + plus t1 = threading.Thread(target=func,args=(v1,1)) t1.start() t2 = threading.Thread(target=func,args=(v2,100)) t2.start() 2. IO操做 多線程有用 import threading import requests import uuid url_list = [ 'https://www3.autoimg.cn/newsdfs/g28/M05/F9/98/120x90_0_autohomecar__ChsEnluQmUmARAhAAAFES6mpmTM281.jpg', 'https://www2.autoimg.cn/newsdfs/g28/M09/FC/06/120x90_0_autohomecar__ChcCR1uQlD6AT4P3AAGRMJX7834274.jpg', 'https://www2.autoimg.cn/newsdfs/g3/M00/C6/A9/120x90_0_autohomecar__ChsEkVuPsdqAQz3zAAEYvWuAspI061.jpg', ] def task(url): ret = requests.get(url) file_name = str(uuid.uuid4()) + '.jpg' with open(file_name, mode='wb') as f: f.write(ret.content) for url in url_list: t = threading.Thread(target=task,args=(url,)) t.start()
四、多線程的問題函數
# by luffycity.com import time import threading lock = threading.RLock() n = 10 def task(i): print('這段代碼不加鎖',i) lock.acquire() # 加鎖,此區域的代碼同一時刻只能有一個線程執行 global n print('當前線程',i,'讀取到的n值爲:',n) n = i time.sleep(1) print('當前線程',i,'修改n值爲:',n) lock.release() # 釋放鎖 for i in range(10): t = threading.Thread(target=task,args=(i,)) t.start()
五、區別ui
Python多線程狀況下: - 計算密集型操做:效率低。(GIL鎖) - IO操做: 效率高 Python多進程的狀況下: - 計算密集型操做:效率高(浪費資源)。 不得已而爲之。 - IO操做: 效率高 (浪費資源)。 之後寫Python時: IO密集型用多線程: 文件/輸入輸出/socket網絡通訊 計算密集型用多進程。 擴展: Java多線程狀況下: - 計算密集型操做:效率高。 - IO操做: 效率高 Python多進程的狀況下: - 計算密集型操做:效率高(浪費資源)。 - IO操做: 效率高 浪費資源)。 Python中線程和進程(GIL鎖) GIL鎖,全局解釋器鎖。用於限制一個進程中同一時刻只有一個線程被cpu調度。 擴展:默認GIL鎖在執行100個cpu指令(過時時間)。