亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

如何在Python中編寫并發程序

系統 1531 0

GIL

在Python中,由于歷史原因(GIL),使得Python中多線程的效果非常不理想.GIL使得任何時刻Python只能利用一個CPU核,并且它的調度算法簡單粗暴:多線程中,讓每個線程運行一段時間t,然后強行掛起該線程,繼而去運行其他線程,如此周而復始,直到所有線程結束.

這使得無法有效利用計算機系統中的"局部性",頻繁的線程切換也對緩存不是很友好,造成資源的浪費.

據說Python官方曾經實現了一個去除GIL的Python解釋器,但是其效果還不如有GIL的解釋器,遂放棄.后來Python官方推出了"利用多進程替代多線程"的方案,在Python3中也有concurrent.futures這樣的包,讓我們的程序編寫可以做到"簡單和性能兼得".

多進程/多線程+Queue

一般來說,在Python中編寫并發程序的經驗是:計算密集型任務使用多進程,IO密集型任務使用多進程或者多線程.另外,因為涉及到資源共享,所以需要同步鎖等一系列麻煩的步驟,代碼編寫不直觀.另外一種好的思路是利用多進程/多線程+Queue的方法,可以避免加鎖這樣麻煩低效的方式.

現在在Python2中利用Queue+多進程的方法來處理一個IO密集型任務.

假設現在需要下載多個網頁內容并進行解析,單進程的方式效率很低,所以使用多進程/多線程勢在必行.
我們可以先初始化一個tasks隊列,里面將要存儲的是一系列dest_url,同時開啟4個進程向tasks中取任務然后執行,處理結果存儲在一個results隊列中,最后對results中的結果進行解析.最后關閉兩個隊列.

下面是一些主要的邏輯代碼.

            
# -*- coding:utf-8 -*-

#IO密集型任務
#多個進程同時下載多個網頁
#利用Queue+多進程
#由于是IO密集型,所以同樣可以利用threading模塊

import multiprocessing

def main():
  tasks = multiprocessing.JoinableQueue()
  results = multiprocessing.Queue()
  cpu_count = multiprocessing.cpu_count() #進程數目==CPU核數目

  create_process(tasks, results, cpu_count)  #主進程馬上創建一系列進程,但是由于阻塞隊列tasks開始為空,副進程全部被阻塞
  add_tasks(tasks) #開始往tasks中添加任務
  parse(tasks, results) #最后主進程等待其他線程處理完成結果


def create_process(tasks, results, cpu_count):
  for _ in range(cpu_count):
    p = multiprocessing.Process(target=_worker, args=(tasks, results)) #根據_worker創建對應的進程
    p.daemon = True #讓所有進程可以隨主進程結束而結束
    p.start() #啟動

def _worker(tasks, results):
  while True:  #因為前面所有線程都設置了daemon=True,故不會無限循環
    try:
      task = tasks.get()  #如果tasks中沒有任務,則阻塞
      result = _download(task)
      results.put(result)  #some exceptions do not handled
    finally:
      tasks.task_done()

def add_tasks(tasks):
  for url in get_urls(): #get_urls() return a urls_list
    tasks.put(url)

def parse(tasks, results):
  try: 
    tasks.join()
  except KeyboardInterrupt as err:
    print "Tasks has been stopped!"
    print err

  while not results.empty():
    _parse(results)



if __name__ == '__main__':
  main()


          

利用Python3中的concurrent.futures包

在Python3中可以利用concurrent.futures包,編寫更加簡單易用的多線程/多進程代碼.其使用感覺和Java的concurrent框架很相似(借鑒?)
比如下面的簡單代碼示例

            
def handler():
  futures = set()

  with concurrent.futures.ProcessPoolExecutor(max_workers=cpu_count) as executor:
    for task in get_task(tasks):
      future = executor.submit(task)
      futures.add(future)

def wait_for(futures):
  try:
    for future in concurrent.futures.as_completed(futures):
      err = futures.exception()
      if not err:
        result = future.result()
      else:
        raise err
  except KeyboardInterrupt as e:
    for future in futures:
      future.cancel()
    print "Task has been canceled!"
    print e
  return result


          

總結

要是一些大型Python項目也這般編寫,那么效率也太低了.在Python中有許多已有的框架使用,使用它們起來更加高效.
但是自己的一些"小打小鬧"的程序這樣來編寫還是不錯的.:)


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 免费国产成人综合 | 欧美一区二区久久精品 | 天天伊人网| 成人网中文字幕色 | 欧美日韩小视频 | 免费观看四虎精品成人 | 久久久久久久久久免费视频 | 国产粉嫩白浆在线观看 | 99热久久国产这里有只有精品 | 日产国产欧美视频一区精品 | 天天色综合2 | 男人的天堂在线视频 | free性欧美极度另类超级大 | 五月激情久久 | 欧美日本高清动作片www网站 | 一级毛片免费视频观看 | 狠狠综合视频精品播放 | 国产不卡视频在线观看 | 久久天天躁狠狠躁夜夜爽蜜月 | 久久精品国产亚洲网站 | 四虎. com 官网| 爱爱免费观看高清视频在线播放 | xxx色视频| 久久久久久97 | 日韩黄色网| 中文字幕国产精品 | 97影院理伦在线观看 | 色综合欧美亚洲另类久久 | 黄色录像欧美 | 国产精品久久久久秋霞影视 | 久久天天躁狠狠躁夜夜爽 | 中文日韩字幕一区在线观看 | 奇米影音四色 | 亚洲欧美色鬼久久综合 | 天天天天躁天天天天碰 | 国产精品免费大片 | 日韩中文字幕网站 | 亚洲国产成人综合 | 国产人成午夜免视频网站 | 特黄a大片免费视频 | 欧美孕妇乱大交xxxxx |