成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何在Python 的線程中運行協程

開發 后端
在一篇文章理解Python異步編程的基本原理這篇文章中,我們講到,如果在異步代碼里面又包含了一段非常耗時的同步代碼,異步代碼就會被卡住。

 在一篇文章理解Python異步編程的基本原理這篇文章中,我們講到,如果在異步代碼里面又包含了一段非常耗時的同步代碼,異步代碼就會被卡住。

[[315885]]

那么有沒有辦法讓同步代碼與異步代碼看起來也是同時運行的呢?方法就是使用事件循環的.run_in_executor()方法。

我們來看一下 Python 官方文檔[1]中的說法:

 

那么怎么使用呢?還是以非常耗時的遞歸方式計算斐波那契數列的這個函數為例:

 

  1. def sync_calc_fib(n): 
  2.     if n in [1, 2]: 
  3.         return1 
  4.     return sync_calc_fib(n - 1) + sync_calc_fib(n - 2) 
  5.  
  6.  
  7. async def calc_fib(n): 
  8.     result = sync_calc_fib(n) 
  9.     print(f'第 {n} 項計算完成,結果是:{result}'
  10.     return result 

我們現在需要用 aiohttp 訪問一個延遲5秒的網頁,同時計算斐波那契數列第36項。

首先我們看看單獨計算第36項需要5秒鐘:

 

我們再來看看如果直接把這計算斐波那契數列和請求網站的兩個異步任務放在一起“并行”,實際時間是兩個任務的時間疊加:

具體原因我在上一篇文章里面已經做了說明。

 

現在,我想讓兩個任務“同時運行”,于是就可以這樣修改代碼:

 

  1. import aiohttp 
  2. import asyncio 
  3. import time 
  4. from concurrent.futures import ThreadPoolExecutor 
  5.  
  6.  
  7. async def request(sleep_time): 
  8.     async with aiohttp.ClientSession() as client: 
  9.         resp = await client.get(f'http://127.0.0.1:8000/sleep/{sleep_time}'
  10.         resp_json = await resp.json() 
  11.         print(resp_json) 
  12.  
  13.  
  14. def sync_calc_fib(n): 
  15.     if n in [1, 2]: 
  16.         return 1 
  17.     return sync_calc_fib(n - 1) + sync_calc_fib(n - 2) 
  18.  
  19.  
  20. def calc_fib(n): 
  21.     result = sync_calc_fib(n) 
  22.     print(f'第 {n} 項計算完成,結果是:{result}'
  23.     return result 
  24.  
  25.  
  26. async def main(): 
  27.     start = time.perf_counter() 
  28.     loop = asyncio.get_event_loop() 
  29.     with ThreadPoolExecutor(max_workers=4) as executor: 
  30.         tasks_list = [ 
  31.             loop.run_in_executor(executor, calc_fib, 36), 
  32.             asyncio.create_task(request(5)) 
  33.         ] 
  34.         await asyncio.gather(*tasks_list) 
  35.         end = time.perf_counter() 
  36.         print(f'總計耗時:{end - start}'
  37.  
  38.  
  39. asyncio.run(main()) 

運行效果如下圖所示:

 

在5秒鐘的時間,就把計算斐波那契數列和請求5秒延遲的網站都做完了。

實現這樣的轉變,關鍵的代碼就是:loop.run_in_executor(executor, calc_fib, 36)

其中的 loop就是主線程的事件循環(event loop),它是用來調度同一個線程里面的多個協程。

executor是我們使用ThreadPoolExecutor(max_workers=4)創建的一個有4個線程的線程池,calc_fib是一個耗時的同步函數,36是傳入calc_fib的參數。loop.run_in_executor(executor, calc_fib, 36)的意思是說:

  1. 把calc_fib函數放到線程池里面去運行
  2. 給線程池增加一個回調函數,這個回調函數會在運行結束后的下一次事件循環把結果保存下來。

請注意上圖中紅色箭頭對應的calc_fib這是一個同步函數,請與上一篇文章中的異步函數區分開。run_in_executor的第二個參數需要是一個同步函數的函數名。

在上面的例子中,我們創建的是有4個線程的線程池。所以這個線程池最多允許4個阻塞式的同步函數“并行”。

責任編輯:華軒 來源: 未聞Code
相關推薦

2021-09-16 09:59:13

PythonJavaScript代碼

2025-06-26 04:10:00

2020-11-29 17:03:08

進程線程協程

2020-04-07 11:10:30

Python數據線程

2024-02-05 09:06:25

Python協程Asyncio庫

2021-04-25 09:36:20

Go協程線程

2023-10-12 09:46:00

并發模型線程

2021-12-09 06:41:56

Python協程多并發

2023-10-11 07:39:58

Java虛擬線程

2023-11-26 18:35:25

Python編程語言

2017-09-22 16:08:16

Python協程編程

2023-11-17 11:36:59

協程纖程操作系統

2022-04-15 08:54:39

PythonAsync代碼

2017-09-06 09:26:03

Python生成器協程

2025-05-26 02:20:00

并發協程虛擬內存

2025-06-05 01:22:00

線程虛擬內存系統

2022-04-08 07:32:24

JavaJUCThreadLoca

2020-08-04 10:56:09

進程線程協程

2020-11-30 08:25:41

程序員高并發協程

2023-12-05 13:46:09

解密協程線程隊列
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩国产免费观看 | 午夜久久久 | 欧美成人在线影院 | 日韩1区2区 | 日本午夜精品 | 国产黄色在线 | 国产精品视频一二三 | 久久99精品久久久久久琪琪 | 男人天堂社区 | 91精品国产乱码久久蜜臀 | 午夜性色a√在线视频观看9 | 成人一区二区在线 | 欧美精品综合在线 | 99精品国产一区二区青青牛奶 | 天天玩夜夜操 | 国产精品一区二区三区久久久 | 中文字幕在线观看一区二区 | 欧美成人精品 | 国产97人人超碰caoprom | 日日骚网 | 91精品国产乱码久久久久久久久 | 97精品视频在线 | 亚洲一区二区国产 | 日韩欧美高清dvd碟片 | 男女黄网站 | 欧美一区二区在线免费观看 | 成人精品免费视频 | 成人国产一区二区三区精品麻豆 | 国产乱码精品一区二区三区中文 | 国产三级电影网站 | 亚洲精品区 | 国产精品成人国产乱 | 久热精品在线观看视频 | 欧美日韩不卡合集视频 | 日韩精品在线一区 | 国产午夜精品一区二区三区在线观看 | 99国产精品久久久久 | 国产精品国产成人国产三级 | 亚洲欧美日韩久久久 | 亚洲精品成人免费 | 91伊人网 |