python多進程、多線程

1、多進程:

windows環境可以使用multiprocessing中的Process實現,該方法中有is_alive(), join(), run(), start(), terminate()方法:

Process的構造方法:

__init__(self, group=None, target=None, name=None, args=(), kwargs={})

參數說明:

group:進程所屬組,基本不會用到;

target:表示調用對象

args:表示調用對象的位置參數元組

name:別名:

join()方法,和多線程類似,會阻塞主進程/主線程,直到其他進程或線程結束後,在運行主進程/線程;

[比如:當從進程/線程使用join方法後,就會提示主線程,需要等待“我”結束之後纔會繼續執行下去]

# coding=utf-8

import multiprocessing


def do(n):
    name = multiprocessing.current_process().name
    print(name, 'starting')
    print('worker', n)
    return


if __name__ == "__main__":
    numList = []
    for i in range(5):
        p1 = multiprocessing.Process(target=do, args=(i,))
        p2 = multiprocessing.Process(target=do, args=(i,))
        p1.start()
        p2.start()
        p1.join()
        p2.join()
        print("Process end")
2、Pool 

可以提供指定數量的進程供用戶調用,當有新的請求提交到Pool中,如果池還沒有滿,就會創建一個新的進程來執行請求,如果池滿,請求就會告知請先等待,直到池中有進程結束,纔會創建新的進程來執行這些請求。Pool中的主要方法:apply()-python3之後不存在、 apply_async()、map()、close()、terminate()、join()。

apply_async() -非阻塞且支持結果返回進行回調

close() - 關閉進程池

terminate() 結束工作進程,不在處理未處理的任務

join() 主進程阻塞等待子進程的退出,join方法必須再close或terminate之後使用。

import time
from multiprocessing import Pool


def run(f):
    time.sleep(1)
    return f * f


if __name__ == "__main__":
    testFL = [1, 2, 3, 4, 5]
    print("order to run")
    s = time.time()
    for f in testFL:
        run(f)

    e1 = time.time()
    print("order to run"), int(e1 - s)
    print("concurrent")
    pool = Pool(2)
    r1 = pool.map(run, testFL)
    pool.close()
    pool.join()
    e2 = time.time()
    print("run time", int(e2 - e1))
    print(r1)

3、進程間通信-Queue

from multiprocessing import Process, Queue

def func(qq):
    qq.put("hello, Process")

if __name__ == "__main__":
    q = Queue()
    p = Process(target=func, args=(q,))
    p.start()
    print(q.get())
    print(q.get_nowait())
    p.join()

Queue中常用的方法:

  • Queue.qsize()  #獲取隊列的大小
  • Queue.empty() #判斷隊列是否爲空, 空返回True,否則返回False
  • Queue.full()  #判斷隊列是否滿,滿返回True,否則返回False
  • Queue.get([block,[timeout]]) #獲取隊列內容,如果隊列爲空,則阻塞
  • Queue.get_nowait()  #與get()方法類似,不過如果隊列爲空,不等待,拋出空異常
  • Queue.put(item) #將item寫入隊列中,如果隊列已滿,則阻塞
  • Queue.put_nowait(item) #寫入隊列,如果隊列已滿,拋出異常(如果通過循環添加隊列,循環大小超出隊列大小,則一個item也添加不成功)
  • q = Queue(size) # 設置Queue的大小

除了基本的FIFO 隊列外,還提供LIFO 隊列[原則爲後進先出],Priority Queue,存儲元素時,使用優先級設置item在隊列中的順序【q.put(priority, item)】。

4、進程間通信-PIPE 


from multiprocessing import  Process, Pipe

def func(conn):
    conn.send("hello, parent !")
    conn.send("I'm ready!")
    print("parent answer:", conn.recv())
    conn.close()

if __name__ == "__main__":
    par_conn, child_conn = Pipe()
    p = Process(target=func, args=(child_conn,))
    p.start()
    print("child message", par_conn.recv())
    print("parent answer:", par_conn.send("hello son !"))
    p.join()

5、進程間通信manager、

其中,managers子模塊支持把多進程分佈到多臺機器上,一個服務器進程作爲調用者,多個客戶端連接到服務器進程,執行多進程任務。

# job類
class Job:
    def __init__(self, job_id):
        self.job_id = job_id
#進程服務器
from multiprocessing import  Queue
from multiprocessing.managers import  BaseManager
from job import Job

class Master:

    def __init__(self):
        self.dispatched_job_queue = Queue()
        self.finished_job_queue = Queue()

    def get_dispatch_job_queue(self):
        return self.dispatched_job_queue

    def get_finished_job_queue(self):
        return self.finished_job_queue

    def start(self):
        BaseManager.register('get_dispatched_job_queue', callable=self.get_dispatch_job_queue)
        BaseManager.register('get_finished_job_queue', callable=self.get_finished_job_queue)

        key = "jobs".encode()
        manager = BaseManager(address=('127.0.0.1', 9988), authkey=key)
        manager.start()

        dispatched_jobs = manager.get_dispatched_job_queue()
        finished_jobs = manager.get_finished_job_queue()

        job_id = 0
        while True:
            for i in range(0, 10):
                job_id = job_id + 1
                job = Job(job_id)
                print('Dispatch job: %s' % job.job_id)
                dispatched_jobs.put(job)

            while not dispatched_jobs.empty():
                job = finished_jobs.get(60)
                print('Finished job: %s' % job.job_id)

        manager.shutdown()
if __name__ == "__main__":
    master = Master()
    master.start()
# 客戶端進程
# coding: utf-8

from multiprocessing import Queue
from multiprocessing.managers import BaseManager
from job import Job
import  time

class Slave:
    def __init__(self):
        self.dispatched_job_queue = Queue()
        self.finished_job_queue = Queue()

    def start(self):
        BaseManager.register('get_dispatched_job_queue')
        BaseManager.register('get_finished_job_queue')

        server = '127.0.0.1'
        key = 'jobs'.encode()

        print("Connect to server %s... " % server)
        manager = BaseManager(address=(server, 9988), authkey=key)
        manager.connect()

        dispatched_jobs = manager.get_dispatched_job_queue()
        finished_jobs = manager.get_finished_job_queue()

        while True:
            job = dispatched_jobs.get(timeout = 1)
            print('Run job: %s' % job.job_id)
            time.sleep(1)
            finished_jobs.put(job)

if __name__ == "__main__":
    slave = Slave()
    slave.start()





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章