Python yield 實現線程內參與者模式(線程內併發)

參與者模式:【摘自維基百科】html

       參與者模型推崇的哲學是「一切皆是參與者」,這與面向對象編程的「一切皆是對象」相似,可是面向對象編程一般是順序執行的,而參與者模型是並行執行的。
參與者是一個運算實體,迴應接受到的消息,同時並行的:python

  • 發送有限數量的消息給其餘參與者;
  • 建立有限數量的新參與者;
  • 指定接受到下一個消息時的行爲。
  • 以上操做不含有順序執行的假設,所以能夠並行進行。

       發送者與已經發送的消息解耦,是參與者模型的根本優點。這容許進行異步通訊,同時知足消息傳遞的控制結構。
        消息接收者是經過地址區分的,有時也被稱做「郵件地址」。所以參與者只能和它擁有地址的參與者通訊。它能夠經過接受到的信息獲取地址,或者獲取它建立的參與者的地址。
        參與者模型的特徵是,參與者內部或之間進行並行計算,參與者能夠動態建立,參與者地址包含在消息中,交互只有經過直接的異步消息通訊,不限制消息到達的順序。編程

python yield 實現的參與者模式:【摘自python3-cookbookapp

from collections import deque

class ActorScheduler:
    def __init__(self):
        self._actors = { }          # Mapping of names to actors
        self._msg_queue = deque()   # Message queue

    def new_actor(self, name, actor):
        '''
        Admit a newly started actor to the scheduler and give it a name
        '''
        self._msg_queue.append((actor,None))
        self._actors[name] = actor

    def send(self, name, msg):
        '''
        Send a message to a named actor
        '''
        actor = self._actors.get(name)
        if actor:
            self._msg_queue.append((actor,msg))

    def run(self):
        '''
        Run as long as there are pending messages.
        '''
        while self._msg_queue:
            actor, msg = self._msg_queue.popleft()
            try:
                 actor.send(msg)
            except StopIteration:
                 pass

# Example use
if __name__ == '__main__':
    def printer():
        while True:
            msg = yield
            print('Got:', msg)

    def counter(sched):
        while True:
            # Receive the current count
            n = yield
            if n == 0:
                break
            # Send to the printer task
            sched.send('printer', n)
            # Send the next count to the counter task (recursive)

            sched.send('counter', n-1)

    sched = ActorScheduler()
    # Create the initial actors
    sched.new_actor('printer', printer())
    sched.new_actor('counter', counter(sched))

    # Send an initial message to the counter to initiate
    sched.send('counter', 10000)
    sched.run()
相關文章
相關標籤/搜索