python多進程(二)

來源:互聯網
上載者:User

標籤:pool   允許   start   sel   管理   ict   sem   cti   server進程   

 

之前實現的資料共用的方式只有兩種結構Value和Array。Python中提供了強大的Manager專門用來做資料共用的,Manager是進程間資料共用的進階介面。 Manager()返回的manager對象控制了一個server進程,此進程包含的python對象可以被其他的進程通過proxies來訪問。從而達到多進程間資料通訊且安全。Manager支援的類型有list, dict, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Queue, Value和Array。

 

下面看一個用於多進程共用dict和list資料:

from multiprocessing import Manager, Processdef worker(dt, lt):    for i in range(10):        dt[i] = i*i  # 訪問共用資料    lt += [x for x in range(11, 16)]if __name__ == ‘__main__‘:    manager = Manager()    dt = manager.dict()    lt = manager.list()    p = Process(target=worker, args=(dt, lt))    p.start()    p.join(timeout=3)    print(dt)    print(lt)
結果:{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}[11, 12, 13, 14, 15]

 

進程池

當使用Process類管理非常多(幾十上百個)的進程時,就會顯得比較繁瑣,Pool可以提供指定數量的進程,供使用者調用,當有新的請求提交到pool中時,如果池還沒有滿,那麼就會建立一個新的進程用來執行該請求;但如果池中的進程數已經達到規定最大值,那麼該請求就會等待,直到池中有進程結束,才會建立新的進程。

import timeimport multiprocessingdef fun(msg):    print("#########start#### {0}".format(msg))    time.sleep(3)    print("#########end###### {0}".format(msg))if __name__ == ‘__main__‘:    print("start main")    pool = multiprocessing.Pool(processes=3) #在進程池中建立3個進程    for i in range(1, 7):        msg = "hello {0}".format(i)        pool.apply_async(fun, (msg,))# 執行時間6s+        # pool.apply(fun, (msg,))    #執行時間 6*3=18s+    pool.close()   #在調用join之前,要先調用close,否則會報錯,close執行完不會有新的進程加入到pool    pool.join()    #join 是等待所有的子進程結束,必須在close之後調用    print("end main")結果:start mainstart hello 1start hello 2start hello 3end hello 1start hello 4end hello 2start hello 5end hello 3start hello 6end hello 4end hello 5end hello 6end main6.18000006676  # 使用pool.apply_async()所花費時間18.2129998207  # 使用pool.apply()所花費時間

pool.apply_async   非阻塞,定義的進程池最大數的同時執行

pool.apply         一個進程結束,釋放回進程池,開始下一個進程

從上面的結果中我們可以看到,使用pool.apply_async所花費的時間較少。

 

多線程

 

Python中提供了threading模組來對多線程進行操作,線程是應用程式中工作的最小單元,多線程適用於密集型io。

多線程的實現方式有兩種:
方法一:將要執行的方法作為參數傳給Thread的構造方法(和多進程類似)
t = threading.Thread(target=action, args=(i,))

方法二:從Thread類繼承,並重寫run()方法。

 

方法一樣本:

import threadingdef worker(args):    print("開始子進程 {0}".format(args))    print("結束子進程 {0}".format(args))if __name__ == ‘__main__‘:    print("start main")    t1 = threading.Thread(target=worker, args=(1,))  # 和多進程類似    t2 = threading.Thread(target=worker, args=(2,))    t1.start()    t2.start()    print("end main")    結果:start main開始子進程 1結束子進程 1開始子進程 2end main結束子進程 2

 

方法二樣本:

import threadingimport timeclass Hello(threading.Thread):
# 對run()方法進行重寫 def __init__(self, args): super(Hello, self).__init__() self.args = args def run(self): print("開始子進程 {0}".format(self.args)) time.sleep(1) print("結束子進程 {0}".format(self.args))if __name__ == ‘__main__‘: a = 1 print("start main") t1 = Hello(1) t2 = Hello(2) t1.start() t2.start() print("end main")結果:start main開始子進程 1開始子進程 2end main結束子進程 2結束子進程 1

 

線程鎖

 

當多線程爭奪鎖時,允許第一個獲得鎖的線程進入臨街區,並執行代碼。所有之後到達的線程將被阻塞,直到第一個線程執行結束,退出臨街區,並釋放鎖。
需要注意,那些阻塞的線程是沒有順序的。

import timeimport threadingdef sub():    global count    lock.acquire()  #上鎖,第一個線程如果申請到鎖,會在執行公用資料的過程中持續阻塞後續線程                    #即後續第二個或其他線程依次來了發現已經被上鎖,只能等待第一個線程釋放鎖                    #當第一個線程將鎖釋放,後續的線程會進行爭搶    ‘‘‘線程的公用資料‘‘‘    temp=count    print("temp is {0}".format(temp))    time.sleep(0.001)    count=temp+1    print("count is {0}".format(count))    ‘‘‘線程的公用資料‘‘‘    lock.release()  # 釋放鎖    time.sleep(2)count=0l=[]lock=threading.Lock()   for i in range(100):    t=threading.Thread(target=sub,args=())    t.start()    l.append(t)for t in l:    t.join()print(count)結果:100

 

線程池


採用線程池,花費的時間更少。

文法結構樣本:

import threadpool  def ThreadFun(arg1,arg2):      pass  def main():      device_list=[object1,object2,object3......,objectn]#需要處理的裝置個數      task_pool=threadpool.ThreadPool(8)#8是線程池中線程的個數      request_list=[]#存放工作清單      #首先構造工作清單      for device in device_list:          request_list.append(threadpool.makeRequests(ThreadFun,[((device, ), {})]))      #將每個任務放到線程池中,等待線程池中線程各自讀取任務,然後進行處理,使用了map函數,不瞭解的可以去瞭解一下。      map(task_pool.putRequest,request_list)      #等待所有任務處理完成,則返回,如果沒有處理完,則一直阻塞      task_pool.poll()  if __name__=="__main__":      main()

 

pip install threadpool   # 安裝threadpool
from threadpool import *   #匯入模組
pool = ThreadPool(size) # 定義一個線程池,最多能建立size個線程
requests = makeRequests() # 調用makeRequests建立了要開啟多線程的函數,以及函數相關參數和回呼函數,其中回呼函數可以不寫,default是無,也就是說makeRequests只需要2個參數就可以運行;
[pool.putRequest(req) for req in requests] # 將所有要運行多線程的請求扔進線程池
pool.wait() # 等待所有的線程完成工作後退出。

[pool.putRequest(req) for req in requests]等同於:
for req in requests:
    pool.putRequest(req)

 

 

例子:

import threadpooldef hello(m, n, o):    print("m = {0}  n={1}  o={2}".format(m, n, o))if __name__ == ‘__main__‘:    # 方法1    lst_vars_1 = [‘1‘, ‘2‘, ‘3‘]   # 需要處理的線程個數    lst_vars_2 = [‘4‘, ‘5‘, ‘6‘]    func_var = [(lst_vars_1, None), (lst_vars_2, None)]    # 方法2    # dict_vars_1 = {‘m‘: ‘1‘, ‘n‘: ‘2‘, ‘o‘: ‘3‘}    # dict_vars_2 = {‘m‘: ‘4‘, ‘n‘: ‘5‘, ‘o‘: ‘6‘}    # func_var = [(None, dict_vars_1), (None, dict_vars_2)]    pool = threadpool.ThreadPool(2)  # 線程池中的線程個數    requests = threadpool.makeRequests(hello, func_var)  # 建立了要開啟多線程的函數,建立需要線程池處理的任務,只需要兩個參數    [pool.putRequest(req) for req in requests]  # 將每個任務放入到線程池中    pool.wait()結果:m = 1  n=2  o=3m = 4  n=5  o=6

 

python多進程(二)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.