原創博客地址:python進階21之actor
actor模型。actor模式是一種最古老的也是最簡單的並行和分佈式計算解決方案。
優點:充分利用單線程+事件機制,達到了多線程效果。
缺點,對python而言,由於GIL的存在,畢竟只是單線程,難以匹敵多進程,目前使用並不多。
簡單任務調度器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
class TaskScheduler: def __init__(self): self._task_queue = deque() def new_task(self, task): ''' Admit a newly started task to the scheduler ''' self._task_queue.append(task) def run(self): ''' Run until there are no more tasks ''' while self._task_queue: task = self._task_queue.popleft() try: # Run until the next yield statement next(task) self._task_queue.append(task) except StopIteration: # Generator is no longer executing pass # Example use sched = TaskScheduler() sched.new_task(countdown(10)) sched.new_task(countdown(5)) sched.new_task(countup(15)) sched.run() |
協程生產者消費者
廖雪峯的python官網教程裏面的協程生產者消費者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
def consumer(): r = '' while True: n = yield r if not n: return print('[CONSUMER] Consuming %s...' % n) r = '200 OK' def produce(c): c.send(None) n = 0 while n < 5: n = n + 1 print('[PRODUCER] Producing %s...' % n) r = c.send(n) print('[PRODUCER] Consumer return: %s' % r) c.close() c = consumer() produce(c) |
併發網絡應用程序
演示了使用生成器來實現一個併發網絡應用程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
class ActorScheduler: def __init__(self): self._actors = {} self._msg_queue = deque() def new_actor(self, name, actor): self._msg_queue.append((actor, None)) self._actors[name] = actor def send(self, name, msg): actor = self._actors.get(name) if actor: self._msg_queue.append((actor, msg)) def run(self): while self._msg_queue: # print("隊列:", self._msg_queue) actor, msg = self._msg_queue.popleft() # print("actor", actor) # print("msg", msg) try: actor.send(msg) except StopIteration: pass if __name__ == '__main__': def say_hello(): while True: msg = yield print("say hello", msg) def say_hi(): while True: msg = yield print("say hi", msg) def counter(sched): while True: n = yield print("counter:", n) if n == 0: break sched.send('say_hello', n) sched.send('say_hi', n) sched.send('counter', n-1) sched = ActorScheduler() # 創建初始化 actors sched.new_actor('say_hello', say_hello()) sched.new_actor('say_hi', say_hi()) sched.new_actor('counter', counter(sched)) sched.send('counter', 10) sched.run() |
參考
擴展Python Gevent的Actor模型:https://www.dazhuanlan.com/2020/02/29/5e5a7f241ed15/
終結python協程—-從yield到actor模型的實現:https://www.bbsmax.com/A/n2d9bQaYzD/
12.12 使用生成器代替線程:https://python3-cookbook.readthedocs.io/zh_CN/latest/c12/p12_using_generators_as_alternative_to_threads.html