9

我知道这听起来很重,但我正在尝试解决一个假设的情况。想象一下,你有N个对象的 N 个观察者。每个人都对对象状态感兴趣。当应用观察者模式时,可观察notify()|update()对象倾向于通过调用观察者方法来遍历其观察者列表。

现在想象一个特定的观察者对可观察对象的状态有很多工作要做。例如,这会减慢最后一次通知的速度。

因此,为了避免减慢对所有观察者的通知速度,我们可以做的一件事是在单独的线程中通知观察者。为了让它工作,我想每个观察者都需要一个线程。这是我们为了避免因繁重的工作而导致通知速度变慢而承受的痛苦开销。如果使用线程方法,比减慢速度更糟糕的是无限循环导致的死线程。阅读经验丰富的程序员对于这一点将是很棒的。

  • 在设计问题上有多年经验的人是怎么想的?
  • 这是一个没有实质性解决方案的问题吗?
  • 这真的是个坏主意吗?为什么?

例子

这是一个模糊的示例,以演示并希望澄清我什至没有测试过的基本思想:

class Observable(object):
    def __init__(self):
        self.queues = {}

    def addObserver(self, observer):
        if not observer in self.queues:
            self.queues[observer] = Queue()
            ot = ObserverThread(observer, self.queues[observer])
            ot.start()

    def removeObserver(self, observer):
        if observer in self.queues:
            self.queues[observer].put('die')
            del self.queues[observer]

    def notifyObservers(self, state):
        for queue in self.queues.values():
            queue.put(state)

class ObserverThread(Thread):
    def __init__(self, observer, queue):
        self.observer = observer
        self.queue = queue

    def run(self):
        running = True
        while running:
            state = self.queue.get()
            if state == 'die':
                running = False
            else:
                self.observer.stateChanged(state)
4

4 回答 4

7

你在正确的轨道上。

每个观察者拥有自己的输入队列和自己的消息处理线程是很常见的(或者更好的是:队列拥有线程,观察者拥有队列)。请参阅活动对象模式

不过也有一些陷阱:

  • 如果您有 100 或 1000 的观察者,您可能需要使用线程池模式
  • 请注意,您将失去对事件处理顺序的控制(哪个观察者首先处理事件)。这可能不是问题,或者可能会打开一个包含非常难以检测的错误的潘多拉盒子。这取决于您的具体应用。
  • 您可能必须处理观察者在通知者之前被删除的情况。这可能有点难以正确处理。
  • 您需要实现消息而不是调用函数。消息生成可能需要更多资源,因为您可能需要分配内存、复制对象等。您甚至可能希望通过为常见消息类型实现消息池来进行优化(您也可以选择实现包装此类池的消息工厂)。
  • 为了进一步优化,您可能希望生成一条消息并将其发送给所有观察者(而不是生成同一消息的多个副本)。您可能需要为您的消息使用一些引用计数机制。
于 2012-12-06T14:05:12.273 回答
2

让每个观察者自己决定它的反应是否是重量级的,如果是,则启动一个线程,或者向线程池提交一个任务。在单独的线程中发出通知并不是一个好的解决方案:在释放可观察对象的同时,它限制了单线程通知的处理器能力。如果您不信任您的观察者,则创建一个线程池,并为每个通知创建一个任务并将其提交到池中。

于 2012-12-09T03:27:43.553 回答
0

在我看来,当一个 Observable 的 Observer 数量很大时,它们会进行繁重的处理,那么最好的办法就是notify()在 Observer 中有一个方法。

用途notify():只是为了在to中设置dirty标志。因此,只要 Observer 线程发现它合适,它就会查询Observable 以获取所需的更新。Observertrue

这不需要在Observable侧面进行繁重的处理并将负载转移到Observer侧面。

现在这取决于Observers他们何时必须观察。

于 2012-12-06T14:01:33.390 回答
0

@Pathai 的答案在很多情况下都是有效的。

一是您正在观察数据库中的变化。在许多方面,您无法仅从快照中重建最终状态,尤其是当您的状态作为复杂查询从数据库中获取时,并且快照是对数据库的更新。

要实现它,我建议使用 Event 对象:

class Observer:
    def __init__(self):
        self.event = threading.Event()

# in observer:
while self.event.wait():
    # do something
    self.event.clear()

# in observable:
observer.event.set()
于 2018-10-19T13:33:25.307 回答