一日一技:等待多個線程同時結束的兩種方法

      網友投稿 659 2025-03-31

      我們在寫多線程代碼的時候,可能會需要等待多個線程同時結束,然后再進行后續的流程。例如,我做了一個聚合搜索引擎,用戶輸入一個關鍵詞,我需要同時在很多個搜索引擎上搜索,然后把搜索結果匯總以后返回給用戶。

      示例代碼如下:

      @app.get('/api/search') def search(keyword: str): google_result = requests.get('Google 搜索地址').text baidu_result = requests.get('百度搜索地址').text bing_result = requests.get('Bing搜索地址').text result = combine(google_result, baidu_result, bing_result) return {'success': True, 'result': result}

      從上面這段代碼,大家可能會發現一個問題,就是在請求多個搜索引擎的時候是串行的,先訪問 Google,訪問完成再訪問百度,訪問完成最后訪問 Bing。這樣顯然會浪費大量的時間。

      如果你不會async/await,那么為了解決這個問題,你能想到的顯然就是使用多線程。使用3個線程同時訪問 Google、百度和 Bing,然后把結果匯總傳入combine函數,不就解決問題了嗎?

      如果僅僅是啟動多個線程,那么做法很簡單:

      import threading def get_url(url): result = requests.get(url, headers=HEADERS).text return result @app.get('/api/search') def search(keyword: str): google_thead = threading.Thread(target=get_url, 'Google 搜索地址') baidu_thread = threading.Thread(target=get_url, '百度搜索地址') bing_thread = threading.Thread(target=get_url, 'Bing搜索地址') google_thread.start() baidu_thread.start() bing_thread.start() ...

      現在問題來了,三個線程確實已經啟動了,但你怎么知道到什么時候為止,所有線程都運行完畢?

      這里我們給出幾個方法。

      使用 join

      調用線程的.join()方法,就可以卡住主線程,直到這個子線程運行完畢才能讓主線程繼續運行后面的代碼。所以我們可以修改代碼為:

      import threading def get_url(url): result = requests.get(url, headers=HEADERS).text return result @app.get('/api/search') def search(keyword: str): google_thead = threading.Thread(target=get_url, 'Google 搜索地址') baidu_thread = threading.Thread(target=get_url, '百度搜索地址') bing_thread = threading.Thread(target=get_url, 'Bing搜索地址') google_thread.start() baidu_thread.start() bing_thread.start() google_thread.join() baidu_thread.join() bing_thread.join()

      一日一技:等待多個線程同時結束的兩種方法

      但等一等,我怎么拿到子線程的返回呢?在默認情況下,你確實拿不到返回的數據。所以你需要傳入一個東西去子線程接收結果。所以代碼可以改為:

      import threading def get_url(url, output): result = requests.get(url, headers=HEADERS).text output.append(result) @app.get('/api/search') def search(keyword: str): result = [] google_thead = threading.Thread(target=get_url, args=['Google 搜索地址', result]) baidu_thread = threading.Thread(target=get_url, args=['百度搜索地址', result]) bing_thread = threading.Thread(target=get_url, args=['Bing搜索地址', result]) google_thread.start() baidu_thread.start() bing_thread.start() google_thread.join() baidu_thread.join() bing_thread.join() combine(*result)

      因為線程是共享內存的,所以他們可以直接修改主線程傳入的列表。

      在使用.join()的時候,需要小心不要把.join()放錯了地方,否則你的多線程就會變成單線程。詳情可以看我的這篇文章:?等一等,你的多線程可別再亂 join 了。

      ThreadPoolExecutor

      Python 自帶了一個concurrent模塊,它就是專門用來處理并發問題的。我們也可以使用這個模塊中的ThreadPoolExecutor來解決問題:

      from concurrent.futures import ThreadPoolExecutor, as_completed def get_url(url): result = requests.get(url, headers=HEADERS).text return result @app.get('/api/search') def search(keyword: str): tasks = [] with ThreadPoolExecutor() as executor: for url in ['Google 搜索地址', '百度搜索地址', 'Bing搜索地址'] task = executor.submit(get_url, url) tasks.append(task) result = [x.result() for x in as_completed(tasks)] combine(*result) ...

      concurrent.futures里面的as_completed函數接收一個列表,列表里面是多個并發任務。當所有并發任務都運行結束時,它才會返回一個可迭代對象。對它進行迭代以后,每個元素的.result()就是每個子線程運行的返回結果。

      其他方法

      除了上面兩個方法外,還可以使用multiprocessing.dummy里面的Pool來實現更簡單的多線程。

      任務調度

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:怎么將大寫字母全部換成小寫字母?(怎樣將大寫字母變成小寫字母)
      下一篇:如何斷開圖表鏈接到Excel中的源數據
      相關文章
      亚洲av无码一区二区三区人妖| 亚洲日韩精品无码专区| 亚洲黄黄黄网站在线观看| 亚洲av永久无码一区二区三区 | 亚洲五月午夜免费在线视频| 亚洲高清国产拍精品熟女| 亚洲日产乱码一二三区别| 一本色道久久88—综合亚洲精品 | 亚洲伊人久久大香线蕉啊| 亚洲国产成人91精品| 亚洲人成电影网站| 亚洲中文无码av永久| 在线观看亚洲AV日韩AV| 亚洲国产综合精品中文第一| 久久亚洲国产成人影院| 亚洲人成网站免费播放| 亚洲av中文无码乱人伦在线观看| 久久人午夜亚洲精品无码区| 另类小说亚洲色图| 亚洲伊人成无码综合网 | 亚洲AV日韩AV一区二区三曲| 色欲aⅴ亚洲情无码AV| 国产精品亚洲五月天高清| 亚洲国产成人久久综合一区77| 亚洲国产专区一区| 在线A亚洲老鸭窝天堂| 亚洲国产精品无码中文字| 亚洲电影免费在线观看| 亚洲卡一卡2卡三卡4麻豆| 亚洲综合色7777情网站777| 亚洲色大情网站www| 精品久久亚洲一级α| 亚洲日本在线观看视频| 亚洲国产日韩在线视频| 亚洲视频中文字幕| 亚洲一级毛片在线观| 亚洲爆乳无码专区www| 亚洲高清国产拍精品青青草原| 在线亚洲人成电影网站色www| 久久久久亚洲AV成人无码网站| 亚洲永久中文字幕在线|