第三十四天- 線程隊列、線程池(map/submit/shutdown/回調函數)

来源:https://www.cnblogs.com/xi1419/archive/2018/12/03/10061410.html
-Advertisement-
Play Games

1.線程列隊 queue隊列 :使用import queue,用法與進程Queue一樣 class queue.Queue(maxsize=0) 1 # 先進先出: 2 q = queue.Queue(3) # 也可以不加數字表示不限 3 q.put('約嗎') 4 q.put('你個糟老頭') 5 ...


 

1.線程列隊

  queue隊列 :使用import queue,用法與進程Queue一樣

 

  class queue.Queue(maxsize=0) 

 1 # 先進先出:
 2 q = queue.Queue(3)  # 也可以不加數字表示不限
 3 q.put('約嗎')
 4 q.put('你個糟老頭')
 5 q.put('約個鬼!')
 6 # q.put_nowait() # 沒有數據會報錯 可以try解決
 7 print(q.get())
 8 print(q.get())
 9 print(q.get())
10 q.get_nowait()
先進先出

  class queue.LifoQueue(maxsize=0)

 1 import queue
 2 
 3 # 後進先出:
 4 q = queue.LifoQueue(4)
 5 q.put('first')
 6 q.put('second')
 7 q.put('third')
 8 q.put_nowait(1)
 9 print(q.get())
10 print(q.get())
11 print(q.get())
12 print(q.get_nowait())
後進先出

  class queue.PriorityQueue(maxsize=0) 

 1 # 設置優先
 2 q = queue.PriorityQueue(6)
 3 
 4 # put進入元組,元組第一個元素是優先順序(通常是數字,也可以是非數字之間的比較),數字越小優先順序越高
 5 q.put((3,'a'))
 6 q.put((2,'b'))
 7 q.put((-3,'c'))
 8 
 9 # 優先順序相同的兩個數據,比較第二個元素ASCII碼大小,若第二元素為字元串且第一個字元相同則比較第二個
10 q.put((20,'ww'))
11 q.put((20,'ws'))
12 # q.put(20,{'ws',22}) # 不能是字典
13 # q.put((20,('w',1))) # 後面的值必須是相同數據類型才能比較,可以是元祖,ascii碼順序排序
14 
15 print(q.get())
16 print(q.get())
17 print(q.get())
18 print(q.get())
19 print(q.get())
20 # print(q.get())
View Code

 

這三種隊列都是線程安全的,不會出現多個線程搶占同一個資源或數據的情況。

 

 

2.線程池

  線程池:早期的時候沒有線程池,現在python提供了一個新的內置模塊 concurrent.futures,模塊裡面提供了新的線程池和進程池,之前的進程池是在multiprocessing裡面,現在這個在這個新的模塊裡面,他倆用法上是一樣的。為了統一使用方式將進程池和線程池放到一起,使用threadPollExecutor和ProcessPollExecutor的方式一樣,且只要通過concurrent.futures導入就可用他們兩個

  基本方法:

 1 #2 基本方法
 2 #submit(fn, *args, **kwargs)
 3 非同步提交任務
 4 
 5 #map(func, *iterables, timeout=None, chunksize=1) 
 6 取代for迴圈submit的操作
 7 
 8 #shutdown(wait=True) 
 9 相當於進程池的pool.close()+pool.join()操作
10 wait=True,等待池內所有任務執行完畢回收完資源後才繼續
11 wait=False,立即返回,並不會等待池內的任務執行完畢
12 但不管wait參數為何值,整個程式都會等到所有任務執行完畢
13 submit和map必須在shutdown之前
14 
15 #result(timeout=None)
16 取得結果
17 
18 #add_done_callback(fn)
19 回調函數
 1 import time
 2 from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
 3 
 4 
 5 def func(n):
 6     time.sleep(0.5)
 7     return n*n
 8 
 9 
10 if __name__ == '__main__':
11     t_pool = ThreadPoolExecutor(max_workers=4)
12     # t_pool = ProcessPoolExecutor(max_workers=4)  # 用concurrent.futures可直接轉換成進程
13     t_list = []
14     for i in range(10):
15         res = t_pool.submit(func,i)  # submit非同步提交任務
16         # print(res.result()) # 等待res的執行結果,拿到了就運行,拿不到就阻塞,放這會變成串列
17         t_list.append(res)
18 
19     t_pool.shutdown()  # 相當於進程池的pool.close() pool.join()
20 
21     print('主線程結束')
22 
23     for res1 in t_list:
24         print(res1.result())
線程池代碼示例
 1 import time
 2 from concurrent.futures import ThreadPoolExecutor
 3 
 4 
 5 def func(n):
 6     time.sleep(1)
 7     return n*n
 8 
 9 
10 if __name__ == '__main__':
11 
12     t_pool = ThreadPoolExecutor(6)
13     res = t_pool.map(func,range(10))  # map 取代for迴圈submit的操作
14     t_pool.shutdown()
15 
16     print('主線程執行結束')
17     for i in res:
18         print(i)
19 
20 # map包含了for迴圈和submit操作
map方法
 1 import time
 2 from concurrent.futures import ThreadPoolExecutor
 3 
 4 
 5 def func1(n):
 6     time.sleep(1)
 7     return n*n
 8 
 9 
10 def callback(s):
11     # print(s)
12     ss = s.result()+1
13     print(ss)
14 
15 
16 if __name__ == '__main__':
17     t_pool = ThreadPoolExecutor(4)
18     for i in range(10):
19         t_pool.submit(func1,i).add_done_callback(callback)
20 
21     # 註意map函數沒有callback,不能如下使用
22     # res = t_pool.map(func1,range(10))
23     # for i in res:
24     #     i.add_done_callback(callback)
回調函數

  需註意:註意map函數沒有callback

 

 

3.GIL鎖

   背景:

  一些語言(java、c++、c)是支持同一個進程中的多個線程是可以應用多核CPU的,也就是我們會聽到的現在4核8核這種多核CPU技術的牛逼之處。那麼我們之前說過應用多進程的時候如果有共用數據是不是會出現數據不安全的問題啊,就是多個進程同時一個文件中去搶這個數據,大家都把這個數據改了,但是還沒來得及去更新到原來的文件中,就被其他進程也計算了,導致數據不安全的問題啊,所以我們是不是通過加鎖可以解決啊,多線程大家想一下是不是一樣的,併發執行就是有這個問題。但是python最早期的時候對於多線程也加鎖,但是python比較極端的(在當時電腦cpu確實只有1核)加了一個GIL全局解釋鎖,是解釋器級別的,鎖的是整個線程,而不是線程裡面的某些數據操作,每次只能有一個線程使用cpu,也就說多線程用不了多核,但是他不是python語言的問題,是CPython解釋器的特性,如果用Jpython解釋器是沒有這個問題的,Cpython是預設的,因為速度快,Jpython是java開發的,在Cpython裡面就是沒辦法用多核,這是python的弊病,歷史問題,雖然眾多python團隊的大神在致力於改變這個情況,但是暫沒有解決。(這和解釋型語言(python,php)和編譯型語言有關係嗎???待定!,編譯型語言一般在編譯的過程中就幫你分配好了,解釋型要邊解釋邊執行,所以為了防止出現數據不安全的情況加上了這個鎖,這是所有解釋型語言的弊端??)

  如圖:

  但是有了這個鎖我們就不能併發了嗎?當我們的程式是偏計算的,也就是cpu占用率很高的程式(cpu一直在計算),就不行了,但是如果你的程式是I/O型的(一般你的程式都是這個)(input、訪問網址網路延遲、打開/關閉文件讀寫),在什麼情況下用的到高併發呢(金融計算會用到,人工智慧(阿爾法狗),但是一般的業務場景用不到,爬網頁,多用戶網站、聊天軟體、處理文件),I/O型的操作很少占用CPU,那麼多線程還是可以併發的,因為cpu只是快速的調度線程,而線程裡面並沒有什麼計算,就像一堆的網路請求,我cpu非常快速的一個一個的將你的多線程調度出去,你的線程就去執行I/O操作了

 

  GIL鎖與Lock:

  GIL保護的是解釋器級的數據,保護用戶自己的數據則需要自己加鎖處理,如下圖

 

 

 

  

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 首先併發編程有三大特性: 可見性,有序性,原子性。volatile關鍵字實現了前面兩個特性。那麼它是如何實現這兩個特性的呢? 首先是可見性。可見性主要是讓緩存,直接寫穿透到主存中。然後另外的cpu 通過底層的硬體層面的嗅探,可以發現自己cpu本地的緩存已經失效。然後到主存中直接讀取。現在讓我們來看看 ...
  • 每種語言都會有字元串的操作,因為字元串是我們平常開發使用頻率最高的一種類型。今天我們來聊一下Java的字元串操作及在某些具體方法中與C#的不同,對於需要熟悉多種語言的人來說,作為一種參考。進行誡勉 首先,什麼是字元串? 字元串是字元的序列,是作為一種對象而存在。說的直白點,字元串就是一些字元的組合, ...
  • 拷貝控制 右值與const引用 背景:當一個函數的返回值是自定義類型時,調用側用什麼類型接收?? 1,如果自定義類型的拷貝構造函數的參數用const修飾了:可以用下麵的方式接收。 2,如果自定義類型的拷貝構造函數的參數沒有用const修飾了:必須用下麵的方式接收 編譯錯誤: 解釋: 第一種條件下,用 ...
  • 值傳遞: (形式參數類型是基本數據類型和String):方法調用時,實際參數把它的值傳遞給對應的形式參數,形式參數只是用實際參數的值初始化自己的存儲單元內容,是兩個不同的存儲單元,所以方法執行中形式參數值的改變不影響實際參數的值。 引用傳遞: (形式參數類型是引用數據類型參數除去String):也稱 ...
  • 學習Java一年多了,練習了很多,這條路真的很難走.還有半年多畢業的我整理整理所學習的筆記給大家分享主要也是讓自己記憶加深.自學時用到的時阿發老師的教學視頻,通俗易懂還有題庫可以練習.最經典的就是阿發老師會教你如何開發車而不是使用車.筆記中的截圖和源碼都是老師的.這次整理主要是給自己看的,有需要的朋 ...
  • 《工作細胞》最近比較火,bilibili 上目前的短評已經有17000多條。 先看分析下頁面 右邊 li 標簽中的就是短評信息,一共20條。一般我們載入大量數據的時候,都會做分頁,但是這個頁面沒有,只有一個滾動條。 隨著滾動條往下拉,信息自動載入了,如下圖,變40條了。由此可見,短評是通過非同步載入的 ...
  • 因為工作中慢慢開始用python的協程,所以想更好的理解一下實現方式,故翻譯此文 原文中把辭彙表放到最後,但是我個人覺得放在最開始比較好,這樣可以增加當你看原文時的理解程度 辭彙表 原生協程函數 Native coroutine function: 由async def定義的協程函數,可以使用awa ...
  • 只使用Spring的時候,我把applicationContext.xml是放在項目的src路徑下的,這樣使用ClassPathXmlApplicationContext很方便嘛 整合了struts之後,就讀取不到這個配置文件了,因為Spring會到WEB-INF下來找配置文件, Spring配置文 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...