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

我以為 Python 多線程沒救了,直到發現 asyncio.to_thread()…真香!

開發
Asyncio.to_thread()讓異步編程更靈活,既享受協程的高效,又能兼容阻塞代碼。但它不是萬能的,線程依然有GIL的限制,關鍵還是得根據場景選擇方案。

作為一名Python開發者,我一度對多線程編程又愛又恨。愛的是它能提高程序效率,恨的是GIL(全局解釋器鎖)和各種死鎖問題,搞得人頭大。尤其是寫異步代碼時,遇到阻塞操作(比如文件IO、網絡請求),整個事件循環都可能被卡住,簡直讓人抓狂!

直到Python 3.9帶來了asyncio.to_thread(),我才發現——原來線程和異步還能這么玩?

1. 曾經的噩夢:阻塞操作卡死事件循環

以前寫異步代碼時,最怕遇到這樣的情況:

import asyncio
import time

async def fetch_data():
    # 模擬一個阻塞操作(比如數據庫查詢)
    time.sleep(2)  # 啊哦,這里會卡住整個事件循環!
    return "Data fetched"

async def main():
    result = await fetch_data()  # 完蛋,整個程序停住了!
    print(result)

asyncio.run(main())

time.sleep()是同步阻塞的,直接調用會讓整個asyncio事件循環卡住2秒,其他任務全得干等著。這顯然不是我們想要的異步效果。

2. 舊時代的解決方案:run_in_executor

在Python 3.9之前,我們通常用loop.run_in_executor()把阻塞操作丟進線程池:

import asyncio
import time

def blocking_task():
    time.sleep(2)
    return "Done"

async def main():
    loop = asyncio.get_event_loop()
    result = await loop.run_in_executor(None, blocking_task)  # 扔進線程池執行
    print(result)

asyncio.run(main())

雖然能用,但代碼有點啰嗦,每次都要手動獲取loop,而且run_in_executor的參數有點反直覺(第一個參數是executor,傳None表示用默認線程池)。

3. Python 3.9的救星:asyncio.to_thread()

然后,Python 3.9帶來了asyncio.to_thread(),讓這一切變得超級簡單:

import asyncio
import time

def blocking_task():
    time.sleep(2)
    return "Done"

async def main():
    result = await asyncio.to_thread(blocking_task)  # 一行搞定!
    print(result)

asyncio.run(main())

優點:

  • 代碼更簡潔:不用手動獲取loop,直接await就行。
  • 語義更清晰:一看就知道是要把函數放到線程里跑。
  • 兼容性不錯:雖然Python 3.9+才原生支持,但3.7~3.8也能用run_in_executor替代。

4. 適用場景:什么時候該用它?

asyncio.to_thread()最適合那些短時間、IO密集型的阻塞操作,比如:

  • 讀寫文件(open() + read())
  • 數據庫查詢(某些同步庫如sqlite3、psycopg2)
  • 網絡請求(requests庫)
  • CPU計算(但如果是長時間計算,建議用multiprocessing)

但不適合:

  • 長時間CPU密集型任務(GIL會限制多線程性能,不如用多進程)。
  • 超高并發場景(線程太多會有調度開銷,不如純異步IO)。

5. 個人踩坑經驗

剛開始用to_thread()時,我犯過一個錯誤:在一個協程里瘋狂開幾百個線程,結果系統資源直接炸了……

async def main():
    tasks = [asyncio.to_thread(blocking_task) for _ in range(1000)]  # 危險!瞬間開1000個線程!
    await asyncio.gather(*tasks)

后來學乖了,改用信號量(asyncio.Semaphore)控制并發:

async def run_with_limit(task_func, max_cnotallow=50):
    semaphore = asyncio.Semaphore(max_concurrency)
    async def wrapper():
        async with semaphore:
            return await asyncio.to_thread(task_func)
    return wrapper

async def main():
    tasks = [run_with_limit(blocking_task)() for _ in range(1000)]
    await asyncio.gather(*tasks)

這樣就能限制最大線程數,避免資源爆炸。

6. 總結:真香,但別濫用

asyncio.to_thread()讓異步編程更靈活,既享受協程的高效,又能兼容阻塞代碼。但它不是萬能的,線程依然有GIL的限制,關鍵還是得根據場景選擇方案:

  • 純異步IO? 直接用aiohttp、asyncpg這類異步庫。
  • 短阻塞操作? to_thread()真香!
  • 長時間CPU計算? 上multiprocessing吧。
責任編輯:趙寧寧 來源: 老貓coder
相關推薦

2020-11-05 11:10:43

程序員開發工具

2019-08-13 09:29:14

Kafka運營數據

2021-03-09 07:37:42

技術Promise測試

2018-09-06 14:18:05

硬盤數據恢復

2020-08-13 10:15:34

MySQL數據庫面試

2009-06-29 17:54:10

Java多線程Thread類創建線程

2019-07-15 16:35:43

MySQL索引阿里

2022-08-29 10:52:37

線程函數操作系統

2020-08-26 10:03:31

MySQL索引

2020-11-04 09:38:05

GitHub代碼開源

2023-03-28 13:01:20

GPT-4開發OpenAI

2014-01-22 09:45:40

2021-08-04 07:57:17

C++多線程算法

2020-06-22 13:48:08

SQL查詢SELECT

2019-10-30 21:27:51

Java中央處理器電腦

2021-04-13 16:05:02

程序員工具軟件

2019-12-19 09:23:45

Java多線程數據

2021-02-05 12:34:33

線程池系統

2010-02-01 17:25:09

Python多線程

2023-10-06 23:06:01

多線程Python
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产视频1区2区 | 亚洲视频一区在线观看 | 亚洲国产小视频 | 欧美日韩视频在线 | 成年人免费看的视频 | 亚洲在线一区二区 | www.亚洲免费| 免费国产一区二区 | 天天躁日日躁狠狠躁2018小说 | 麻豆av一区二区三区久久 | 中文字幕一区二区三区四区五区 | 中文字幕一区二区三区乱码图片 | 黄视频欧美 | 精品国产一区二区国模嫣然 | 色偷偷888欧美精品久久久 | 成人影院av| 99只有精品 | 国产精品海角社区在线观看 | 国产欧美精品一区二区三区 | 久久久久久久久久久久亚洲 | 一区二区成人在线 | 国产欧美精品一区二区色综合 | 九九精品热 | 3级毛片 | 成人av免费网站 | 黄色片视频 | 亚洲精品日日夜夜 | 免费视频色 | 在线91| 久草在线视频中文 | 久久国产视频网站 | 一区二区三区四区在线视频 | 91精品国产综合久久久久久丝袜 | 日韩一区二区三区视频在线播放 | 天天操天天干天天曰 | 久久草视频 | 国产美女一区 | 中文字幕国产一区 | 在线国产99 | 国产精品久久久久久久久久久久冷 | 久久久久久久久99精品 |