程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

python學習筆記之--python的多線程以及並發操作

編輯:Python

python學習筆記之--python的多線程以及並發操作

  • 1、什麼是多線程
  • 2、多線程的作用
  • 3、常見的程序運行方式
  • 4、cpu密集與io密集的區別
  • 5、了解GIL全局解釋器鎖
  • 6、多線程的運用
  • 7、Python中的queue隊列
  • 8、生產者-消費者模式
  • 9、線程池的使用
    • 9.1、submit方法:
    • 9.2、map方法

1、什麼是多線程

說起進程,就不得不說下程序。程序是指令和數據的有序集合,其本身沒有任何運行的含義,是一個靜態的概念。

而進程則是執行程序的一次執行過程,它是一個動態的概念。是系統資源分配的單位
通常在一個進程中可以包含若干個線程,當然一個進程中至少有一個線程,不然沒有存在的意義。線程是CPU調度和執行的的單位。

注意:很多多線程是模擬出來的,真正的多線程是指有多個cpu,即多核,如服務器。如果是模擬出來的多線程,即在一個cpu的情況下,在同一個時間點,cpu只能執行一個代碼,因為切換的很快,所以就有同時執行的錯局。

2、多線程的作用

能大幅度提高程序的運行效率,優化用戶體驗,大大地縮短了程序的運行時間

3、常見的程序運行方式

4、cpu密集與io密集的區別

注意多線程只能進行並發操作,而不能利用多cpu(存在GIL全局解釋器鎖),利用的也是cpu與io可以並行運行的原理

5、了解GIL全局解釋器鎖

全局解釋器鎖(英語:Global Interpreter Lock,縮寫GIL)
是計算機程序設計語言解釋器用於同步線程的一種機制,它使得任何時刻僅有一個線程在執行。
即便在多核心處理器上,使用GIL的解釋器也只允許同一時間執行一個線程。
這也是導致python執行速度慢的一個原因

表示了同一時刻只有一個線程在執行

GIL的作用:主要是為了解決多線程之間數據完整性和狀態同步問題
雖然不能利用多核cpu的優勢,但是還是可以實現cpu與io並行的操作,也可以大幅提升速度

6、多線程的運用

主要用到threading的Thread類

  • target 表示方法名
  • args 表示方法所需的參數
  • Name 表示線程名字

7、Python中的queue隊列

  • Queue.qsize() 返回隊列的大小
  • Queue.empty() 如果隊列為空,返回True,反之False
  • Queue.full() 如果隊列滿了,返回True,反之False
  • Queue.full 與 maxsize 大小對應
  • Queue.get([block[, timeout]])獲取隊列,timeout等待時間
  • Queue.get_nowait() 相當Queue.get(block=False) // block=False表示當沒元素時不等待,直接拋出Empty 異常
  • Queue.put(item) 寫入隊列,timeout等待時間
  • Queue.put_nowait(item) 相當Queue.put(item,block=False) // block=False表示當沒元素時不等待,直接拋出Full異常
  • Queue.task_done() 在完成一項工作之後,Queue.task_done()函數向任務已經完成的隊列發送一個信號
  • Queue.join() 實際上意味著等到隊列為空,再執行別的操作

8、生產者-消費者模式

實際上本質就是,定義一個中間的緩沖區作為生產者與消費者交互的通道,比如餐廳這一場景,以櫃台為中間件,生產者生產好後,就調用中間件中push的方法,消費者消費完後就調用中間件的pop方法,再加一定的數量限制即可
即由中間件容器創造資源的增刪改的操作
消費者就只負責消費商品,進行刪的獲取操作
生產者就負責生產商品,負責增加的操作


9、線程池的使用

系統啟動一個新線程的成本是比較高的,因為它涉及與操作系統的交互。在這種情形下,使用線程池可以很好地提升性能,尤其是當程序中需要創建大量生存期很短暫的線程時,更應該考慮使用線程池,以此來避免過大的線程的創建與銷毀的開銷
線程池在系統啟動時即創建大量空閒的線程,程序只要將一個函數提交給線程池,線程池就會啟動一個空閒的線程來執行它。當該函數執行結束後,該線程並不會死亡,而是再次返回到線程池中變成空閒狀態,等待執行下一個函數
線程的生命周期

線程池使用的是concurrent.futures 下的ThreadPoolExecutor類

  • submit(fn, *args, **kwargs):將 fn 函數提交給線程池。*args 代表傳給 fn 函數的參數,*kwargs 代表以關鍵字參數的形式為 fn 函數傳入參數。
  • map(func, *iterables, timeout=None, chunksize=1):該函數類似於全局函數 map(func, *iterables),只是該函數將會啟動多個線程,以異步方式立即對 iterables 執行 map 處理。
  • shutdown(wait=True):關閉線程池。

9.1、submit方法:

submit方法將傳入的方法交給線程池,後面直接跟參數值或者關鍵字傳值,返回future對象

  • future.result() 方法獲取方法的返回值
  • future.add_done_callback(function) 方法在線程任務完成時自動調用回調方法,此為非阻塞的獲取線程執行的結果,直接future.result()會導致阻塞線程
  • as_completed 函數,通過這個函數遍歷獲取future結果的是異步獲取結果,即哪個任務先完成就先輸出

9.2、map方法

異步執行方法,順序輸出

注意:zip([1,2],[‘a’,’b’]) ==> [(1,’a’),(2,’b’)]


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved