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()
相关文章
相关标签/搜索