python--(十步代碼學會線程)python
一.線程的建立安全
Thread實例對象的方法 # isAlive(): 返回線程是否活動的. # getname(): 返回線程名. # setName(): 設置線程名. threading模塊提供的一些方法: # threading.currentThread(): 返回當前的線程變量。 # threading.enumerate(): 返回一個包含正在運行的線程的list。正在運行指線程啓動後、結束前,不包括啓動前和終止後的線程。 # threading.activeCount(): 返回正在運行的線程數量,與len(threading.enumerate())有相同的結果
from threading import Thread from multiprocessing import Process #第一種方法 def func(n): print(n) if __name__ == '__main__': t = Thread(target=func, args=("我是線程",)) t.start() # p = Process(target=func, args=("我是進程",)) # p.start() print("主進程結束.") #第二種方法 class MyThread(Thread): def run(self): print("輝哥牛逼") if __name__ == "__main__": t = MyThread() t.start() print("主線程結束")
import time from threading import Thread from multiprocessing import Process def func(n): num = 0 for n1 in range(n): num += n1 print("num",num) if __name__ == '__main__': t_s_t = time.time() t_list = [] for i in range(10): t = Thread(target=func, args=(10,)) t.start() #速度特別快 t_list.append(t) [tt.join() for tt in t_list] t_e_t = time.time() t_dif_t = t_s_t - t_e_t #獲取了線程的執行時間 p_s_t = time.time() p_list = [] for ii in range(10): p = Process(target=func, args=(10,)) p.start() #速度很是快 p_list.append(p) [pp.join() for pp in p_list] p_e_t = time.time() #結束時間 p_dif_t = p_e_t - p_s_t #獲取進程執行時間 print('線程>>>>', t_dif_t) print('進程....', p_dif_t) print('主線程結束')
線程的其餘方法app
# 線程的一些其餘方法 # from threading import Thread # import threading # import time # from multiprocessing import Process # import os # # def work(): # import time # time.sleep(1) # print(threading.current_thread().getName()) #Thread-1 # print(threading.current_thread()) #Thtrad-1 # # if __name__ == '__main__': # #在主進程下開啓線程 # t = Thread(target=work) # t.start() # # # print(threading.current_thread()) #主線程對象 # # print(threading.current_thread().getName()) #主線程名稱 # # print(threading.current_thread().ident) #主線程ID # # print(threading.get_ident()) #主線程ID # # time.sleep(3) # print(threading.enumerate()) #連同主線程在內有兩個運行的線程 # print(threading.active_count()) #進程數 # print("主線程/主進程")
二.數據共享異步
from threading import Thread from multiprocessing import Process num = 100 def func(): global num num = 0 if __name__ == '__main__': t = Thread(target=func,) t.start() t.join() print(num) # p = Process(target=func,) # p.start() # p.join() # print(num)
mport time from threading import Thread,Lock #演示共享資源的時候,數據不安全的問題 # num = 100 # def func(): # global num # num -= 1 # mid = num # mid = mid - 1 # time.sleep(0.00001) # num = mid # if __name__ == '__main__': # t_list = [] # for i in range(10): # t = Thread(target=func,) # t.start() # t_list.append(t) # [tt.join() for tt in t_list] # print("主進程>>>>", num) #經過鎖來解決數據不安全的問題,線程模塊裏面引入的鎖 num = 100 def func(t_lock): global num t_lock.acquire() mid = num mid = mid - 1 time.sleep(0.0001) num = mid t_lock.release() if __name__ == '__main__': t_lock = Lock() #鎖對象(同步鎖,互斥鎖) t_list = [] for i in range(10): t = Thread(target=func,args=(t_lock,)) t.start() t_list.append(t) [tt.join() for tt in t_list] print("主進程>>>>",num)
三.守護進程ide
守護進程 :函數
主進程代碼結束程序並無結束,而且主進程還存在,進程等待其餘的子進程執行結束之後,爲子進程收屍,注意一個問題:主進程的代碼運行結束守護進程跟着結束,ui
守護線程:spa
主線程等待全部非守護線程的結束才結束,主線程的代碼運行結束,還要等待非守護線程的執行完畢.這個過程當中守護線程還存在線程
1 import time 2 from threading import Thread 3 from multiprocessing import Process 4 def func1(n): 5 time.sleep(5) 6 print(n) 7 def func2(n): 8 time.sleep(3) 9 print(n) 10 if __name__ == '__main__': 11 # p1 = Process(target=func1,args=("我是子進程1號",)) 12 # #設置守護進程,在start以前加 13 # p1.start() 14 # p2 = Process(target=func2,args=("我是子進程2號",)) 15 # p2.daemon = True 16 # p2.start() 17 # print("子進程結束")
四.死鎖現象3d
鎖(同步鎖\互斥鎖): 保證數據安全,可是犧牲了效率,同步執行鎖內的代碼
死鎖現象 : 互相搶到了對方的須要的鎖,致使雙方相互等待,程序無法進行
解決死鎖: 遞歸鎖,RLock #能夠屢次acquire,經過一個計數器來記錄被鎖了多少次,只有計數器爲0的時候,大 家才能繼續搶鎖
import time from threading import Thread,Lock class MyThread(Thread): def __init__(self,lockA,lockB): super().__init__() self.lockA = lockA self.lockB = lockB def run(self): self.f1() self.f2() def f1(self): self.lockA.acquire() print('我拿了A鎖') self.lockB.acquire() print('我是一個很好的客戶!') self.lockB.release() self.lockA.release() def f2(self): self.lockB.acquire() time.sleep(0.1) print('我拿到了B鎖') self.lockA.acquire() print('我是一名合格的技師') self.lockA.release() self.lockB.release() if __name__ == '__main__': lockA = Lock() lockB = Lock() t1 = MyThread(lockA,lockB) t1.start() t2 = MyThread(lockA,lockB) t2.start() print('我是經理')
import time from threading import Thread,Lock,RLock #遞歸鎖 class MyThread(Thread): def __init__(self,lockA,lockB): super().__init__() self.lockA = lockA self.lockB = lockB def run(self): self.f1() self.f2() def f1(self): self.lockA.acquire() print('我拿了A鎖') self.lockB.acquire() print('我是一個很好的客戶!') self.lockB.release() self.lockA.release() def f2(self): self.lockB.acquire() time.sleep(0.1) print('我拿到了B鎖') self.lockA.acquire() print('我是一名合格的技師') self.lockA.release() self.lockB.release() if __name__ == '__main__': # lockA = Lock() # lockB = Lock() # lockA = lockB = Lock() #不要這麼寫,別本身玩本身,鎖本身 lockA = lockB = RLock() t1 = MyThread(lockA,lockB) t1.start() t2 = MyThread(lockA,lockB) t2.start() print('我是經理')
五.信號量
信號量: 控制同時可以進入鎖內去執行代碼的線程數量(進程數量),維護了一個計數器,剛開始建立信號量的時候假如設置的是4個房間,進入一次acquire就減1 ,出來一個就+1,若是計數器爲0,那麼其餘的任務等待,這樣其餘的任務和正在執行的任務是一個同步的狀態,而進入acquire裏面去執行的那4個任務是異步執行的.
import time from threading import Thread, Semaphore def func1(s): s.acquire() time.sleep(1) print('大寶劍!!!') s.release() if __name__ == '__main__': s = Semaphore(4) for i in range(10): t = Thread(target=func1,args=(s,)) t.start()
六.事件
# # 事件 # from threading import Thread,Event # e = Event() #e的狀態有兩種,False Ture,當事件對象的狀態爲False的時候,wait的位置會阻塞 # # e.set() #將事件對象的狀態改成Ture # e.clear() #將事件對象的狀態改成False # print("在這裏等待") # e.wait() #阻塞 # print("還沒好")
七.隊列
mport queue #先進先出 FIFO # q=queue.Queue() # q.put('first') # q.put('second') # q.put('third') # # q.put_nowait() #沒有數據就報錯,能夠經過try來搞 # print(q.get()) # print(q.get()) # print(q.get()) # # q.get_nowait() #沒有數據就報錯,能夠經過try來搞 # ''' # first # second # third # ''' # 先進後出 # import queue # q = queue.LifoQueue() #隊列相似於棧,先進後出的順序 # q.put('first') # q.put('second') # q.put('third') # q.put_nowait() # print(q.get()) # print(q.get()) # print(q.get()) # # q.get_nowait() #沒有數據就報錯 # ''' # third # second # first # ''' # # 優先級隊列 # import queue # q = queue.PriorityQueue() # #put進入一個元祖,元祖的第一個元素是優先級(一般是數字,也能夠是非數字之間的比較,數字越小優先級越高 # q.put((-10,"a")) # q.put((-5,"a")) #負數也能夠 # # # q.put((20,'b')) #若是第一個參數數字的優先級同樣,那麼按照後面的字符串acsii來排序 # # q.put((20,'c')) # # # q.put((20,{'a':11})) #TypeError: unorderable types: dict() < dict() 不能是字典 # # q.put((20,('w',1))) #優先級相同的兩個數據,他們後面的值必須是相同的數據類型才能比較,能夠是元祖,也是經過元素的ascii碼順序來排序 # # print(q.get()) # print(q.get()) # """結果:數字越小優先級越高,優先級高的優先出隊"""
八.線程池
concurrent.futures模塊提供了高度封裝的異步調用接口 ThreadPoolExecutor:線程池,提供異步調用 ProcessPoolExecutor: 進程池,提供異步調用 Both implement the same interface, which is defined by the abstract Executor class. #2 基本方法 #submit(fn, *args, **kwargs) 異步提交任務 #map(func, *iterables, timeout=None, chunksize=1) 取代for循環submit的操做 #shutdown(wait=True) 至關於進程池的pool.close()+pool.join()操做 wait=True,等待池內全部任務執行完畢回收完資源後才繼續 wait=False,當即返回,並不會等待池內的任務執行完畢 但無論wait參數爲什麼值,整個程序都會等到全部任務執行完畢 submit和map必須在shutdown以前 #result(timeout=None) 取得結果 #add_done_callback(fn) 回調函數
# 線程池 # import time # from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor # #ProcessPoolExecutor 進程池 # from threading import current_thread # # def func(n): # time.sleep(1) # # print(n,current_thread().ident) # return n**2 # if __name__ == '__main__': # t_p = ThreadPoolExecutor(max_workers = 4) # map_res = t_p.map(func,range(10)) #異步執行的,map自帶join功能 # print(map_res) # print([i for i in map_res])
線程池的一些其餘方法
# 線程池的一些其餘方法 # import time # from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor # from threading import current_thread # def func(n): # time.sleep(1) # #print(n,current_thread().ident) # return n**2 # def func2(n): # print(n) # if __name__ == '__main__': # t_p = ThreadPoolExecutor(max_workers=4) # t_p_list = [] # for i in range(10): # res_obj = t_p.submit(func, i) #異步提交了這10個任務 # # res_obj.result() #他和get同樣 # t_p_list.append(res_obj) # t_p.shutdown() #close + join 等待所有完成以後關閉子線程,防止後面數據進入 # # print('t_res_list',t_p_list) # for e_res in t_p_list: # print(e_res.result())
九.回調函數
rom concurrent.futures import ThreadPoolExecutor from threading import current_thread def func(n): time.sleep(1) print(n**2) # print(n,current_thread().getName()) # return n**2 def func2(n): # print("current_thread>>>>",current_thread().getName()) print(n.result()) #result() 至關於 get() if __name__ == '__main__': t_p = ThreadPoolExecutor(max_workers=1) for i in range(3): t_p.submit(func, i).add_done_callback(func2) print('主進程結束')
十.GIL鎖
#保證數據安全,鎖的是整個線程,每次只能有一個線程使用cpu,是CPython解釋器的特性